Merge branches 'acpi-misc' and 'acpi-doc'
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>
Tue, 17 Sep 2019 07:52:21 +0000 (09:52 +0200)
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>
Tue, 17 Sep 2019 07:52:21 +0000 (09:52 +0200)
* acpi-misc:
  ACPI: thermal: Remove redundant acpi_has_method() calls
  ACPI: SBS: remove unused const variable 'SMBUS_PEC'

* acpi-doc:
  Documentation: ACPI: DSD: Convert LED documentation to ReST

339 files changed:
Documentation/PCI/index.rst
Documentation/PCI/pciebus-howto.rst [new file with mode: 0644]
Documentation/PCI/picebus-howto.rst [deleted file]
Documentation/admin-guide/kernel-parameters.txt
Documentation/admin-guide/sysctl/net.rst
Documentation/networking/tls-offload.rst
Documentation/networking/tuntap.txt
MAINTAINERS
Makefile
arch/arm/Kconfig
arch/arm/mach-rpc/riscpc.c
arch/arm/mm/Kconfig
arch/mips/include/asm/octeon/cvmx-sli-defs.h
arch/parisc/include/asm/pgtable.h
arch/um/include/shared/timer-internal.h
arch/um/kernel/process.c
arch/um/kernel/time.c
arch/x86/boot/compressed/pgtable_64.c
arch/x86/events/core.c
arch/x86/include/asm/bootparam_utils.h
arch/x86/include/asm/intel-family.h
arch/x86/include/asm/msr-index.h
arch/x86/include/asm/nospec-branch.h
arch/x86/kernel/apic/apic.c
arch/x86/kernel/cpu/amd.c
arch/x86/kvm/lapic.c
arch/x86/kvm/mmu.c
arch/x86/kvm/svm.c
arch/x86/net/bpf_jit_comp.c
arch/x86/power/cpu.c
drivers/acpi/acpi_lpss.c
drivers/acpi/acpi_processor.c
drivers/acpi/acpica/aclocal.h
drivers/acpi/acpica/acobject.h
drivers/acpi/acpica/acstruct.h
drivers/acpi/acpica/acutils.h
drivers/acpi/acpica/dbhistry.c
drivers/acpi/acpica/dbinput.c
drivers/acpi/acpica/dbmethod.c
drivers/acpi/acpica/dbobject.c
drivers/acpi/acpica/dbstats.c
drivers/acpi/acpica/exdump.c
drivers/acpi/acpica/nsaccess.c
drivers/acpi/acpica/nsalloc.c
drivers/acpi/acpica/nsdump.c
drivers/acpi/acpica/nsrepair2.c
drivers/acpi/acpica/tbdata.c
drivers/acpi/acpica/utdebug.c
drivers/acpi/acpica/uterror.c
drivers/acpi/acpica/utosi.c
drivers/acpi/acpica/utownerid.c
drivers/acpi/apei/ghes.c
drivers/acpi/cppc_acpi.c
drivers/acpi/custom_method.c
drivers/acpi/hmat/hmat.c
drivers/acpi/pci_irq.c
drivers/acpi/pci_link.c
drivers/acpi/sbshc.h
drivers/acpi/thermal.c
drivers/auxdisplay/ht16k33.c
drivers/block/drbd/drbd_main.c
drivers/bluetooth/btqca.c
drivers/bluetooth/btqca.h
drivers/bluetooth/btusb.c
drivers/bluetooth/hci_qca.c
drivers/clk/clk.c
drivers/clk/samsung/clk-exynos5-subcmu.c
drivers/clk/samsung/clk-exynos5-subcmu.h
drivers/clk/samsung/clk-exynos5250.c
drivers/clk/samsung/clk-exynos5420.c
drivers/clk/socfpga/clk-periph-s10.c
drivers/dma/fsldma.c
drivers/gpio/gpiolib-of.c
drivers/gpio/gpiolib.c
drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
drivers/gpu/drm/amd/amdgpu/nv.c
drivers/gpu/drm/amd/amdgpu/soc15.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h
drivers/gpu/drm/amd/powerplay/smu_v11_0.c
drivers/gpu/drm/arm/display/komeda/komeda_dev.c
drivers/gpu/drm/arm/display/komeda/komeda_format_caps.c
drivers/gpu/drm/arm/display/komeda/komeda_format_caps.h
drivers/gpu/drm/arm/display/komeda/komeda_framebuffer.c
drivers/gpu/drm/arm/display/komeda/komeda_kms.c
drivers/gpu/drm/i915/display/intel_ddi.c
drivers/gpu/drm/i915/intel_drv.h
drivers/gpu/drm/mediatek/mtk_drm_drv.c
drivers/gpu/drm/mediatek/mtk_drm_drv.h
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/aux.c
drivers/gpu/drm/omapdrm/omap_drv.c
drivers/gpu/drm/rcar-du/rcar_lvds.c
drivers/gpu/drm/sun4i/sun4i_tcon.c
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
drivers/hid/hid-cp2112.c
drivers/hid/hid-logitech-hidpp.c
drivers/hid/intel-ish-hid/ipc/hw-ish.h
drivers/hid/intel-ish-hid/ipc/pci-ish.c
drivers/hid/wacom_wac.c
drivers/hv/channel.c
drivers/hv/hyperv_vmbus.h
drivers/infiniband/core/cma.c
drivers/infiniband/core/counters.c
drivers/infiniband/core/nldev.c
drivers/infiniband/core/restrack.c
drivers/infiniband/core/umem.c
drivers/infiniband/hw/bnxt_re/qplib_rcfw.c
drivers/infiniband/hw/bnxt_re/qplib_rcfw.h
drivers/infiniband/hw/hfi1/fault.c
drivers/infiniband/hw/hfi1/tid_rdma.c
drivers/infiniband/hw/mlx4/mad.c
drivers/infiniband/hw/mlx5/main.c
drivers/infiniband/hw/mlx5/mem.c
drivers/infiniband/hw/mlx5/mlx5_ib.h
drivers/infiniband/hw/mlx5/mr.c
drivers/infiniband/hw/mlx5/odp.c
drivers/infiniband/hw/mlx5/qp.c
drivers/infiniband/sw/siw/siw.h
drivers/infiniband/sw/siw/siw_cm.c
drivers/infiniband/sw/siw/siw_cq.c
drivers/infiniband/sw/siw/siw_mem.c
drivers/infiniband/sw/siw/siw_mem.h
drivers/infiniband/sw/siw/siw_qp.c
drivers/infiniband/sw/siw/siw_qp_rx.c
drivers/infiniband/sw/siw/siw_qp_tx.c
drivers/infiniband/sw/siw/siw_verbs.c
drivers/input/serio/hyperv-keyboard.c
drivers/iommu/dma-iommu.c
drivers/md/dm-bufio.c
drivers/md/dm-dust.c
drivers/md/dm-integrity.c
drivers/md/dm-kcopyd.c
drivers/md/dm-raid.c
drivers/md/dm-table.c
drivers/md/dm-zoned-metadata.c
drivers/md/dm-zoned-reclaim.c
drivers/md/dm-zoned-target.c
drivers/md/dm-zoned.h
drivers/md/persistent-data/dm-btree.c
drivers/md/persistent-data/dm-space-map-metadata.c
drivers/mtd/maps/sa1100-flash.c
drivers/net/bonding/bond_main.c
drivers/net/dsa/sja1105/sja1105_main.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
drivers/net/ethernet/broadcom/bnxt/bnxt.c
drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c
drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c
drivers/net/ethernet/broadcom/bnxt/bnxt_tc.h
drivers/net/ethernet/cavium/common/cavium_ptp.c
drivers/net/ethernet/cavium/liquidio/request_manager.c
drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c
drivers/net/ethernet/ezchip/nps_enet.h
drivers/net/ethernet/ibm/ibmveth.c
drivers/net/ethernet/ibm/ibmvnic.c
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
drivers/net/ethernet/mellanox/mlx4/en_rx.c
drivers/net/ethernet/mellanox/mlx5/core/en.h
drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c
drivers/net/ethernet/mellanox/mlx5/core/en/xsk/setup.c
drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls.h
drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_tx.c
drivers/net/ethernet/mellanox/mlx5/core/en_arfs.c
drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
drivers/net/ethernet/mellanox/mlx5/core/en_main.c
drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
drivers/net/ethernet/mellanox/mlx5/core/eswitch.h
drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
drivers/net/ethernet/mellanox/mlx5/core/ipoib/ethtool.c
drivers/net/ethernet/mellanox/mlx5/core/lib/crypto.c
drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c
drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c
drivers/net/ethernet/mscc/ocelot_flower.c
drivers/net/ethernet/myricom/myri10ge/myri10ge.c
drivers/net/ethernet/netronome/nfp/flower/qos_conf.c
drivers/net/ethernet/renesas/ravb_main.c
drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c
drivers/net/ethernet/toshiba/tc35815.c
drivers/net/ethernet/tundra/tsi108_eth.c
drivers/net/hyperv/netvsc_drv.c
drivers/net/netdevsim/dev.c
drivers/net/netdevsim/fib.c
drivers/net/netdevsim/netdev.c
drivers/net/netdevsim/netdevsim.h
drivers/net/phy/at803x.c
drivers/net/phy/phy-c45.c
drivers/net/phy/phy_device.c
drivers/net/team/team.c
drivers/net/usb/cx82310_eth.c
drivers/net/usb/kalmia.c
drivers/net/usb/lan78xx.c
drivers/net/wimax/i2400m/fw.c
drivers/net/xen-netback/netback.c
drivers/nvme/host/core.c
drivers/nvme/host/multipath.c
drivers/nvme/host/nvme.h
drivers/nvme/host/pci.c
drivers/pci/quirks.c
drivers/platform/chrome/cros_ec_ishtp.c
drivers/power/supply/ab8500_charger.c
drivers/s390/net/qeth_core.h
drivers/s390/net/qeth_core_main.c
drivers/scsi/libsas/sas_discover.c
drivers/scsi/lpfc/lpfc.h
drivers/scsi/lpfc/lpfc_attr.c
drivers/scsi/lpfc/lpfc_init.c
drivers/scsi/lpfc/lpfc_sli4.h
drivers/scsi/qla2xxx/qla_attr.c
drivers/scsi/qla2xxx/qla_os.c
drivers/scsi/ufs/ufshcd.c
drivers/target/target_core_user.c
drivers/video/fbdev/acornfb.c
drivers/watchdog/wdt285.c
fs/afs/cell.c
fs/afs/dir.c
fs/afs/yfsclient.c
fs/ceph/addr.c
fs/ceph/caps.c
fs/ceph/inode.c
fs/ceph/locks.c
fs/ceph/snap.c
fs/ceph/super.h
fs/ceph/xattr.c
fs/cifs/connect.c
fs/io_uring.c
fs/nfsd/nfscache.c
fs/nfsd/nfsctl.c
fs/read_write.c
fs/ubifs/budget.c
fs/ubifs/orphan.c
fs/ubifs/super.c
fs/userfaultfd.c
fs/xfs/xfs_ioctl32.c
fs/xfs/xfs_iops.c
fs/xfs/xfs_pnfs.c
fs/xfs/xfs_reflink.c
include/acpi/acconfig.h
include/acpi/acpiosxf.h
include/acpi/acpixf.h
include/acpi/actypes.h
include/linux/ceph/buffer.h
include/linux/dma-contiguous.h
include/linux/gpio.h
include/linux/key.h
include/linux/mlx5/device.h
include/linux/mlx5/mlx5_ifc.h
include/linux/signal.h
include/linux/skbuff.h
include/linux/socket.h
include/linux/timekeeper_internal.h
include/net/bluetooth/hci_core.h
include/net/inet_frag.h
include/net/net_namespace.h
include/net/netfilter/nf_tables.h
include/net/netfilter/nf_tables_offload.h
include/net/netlink.h
include/net/pkt_cls.h
include/net/sock.h
include/rdma/restrack.h
include/trace/events/rxrpc.h
include/uapi/linux/bpf.h
include/uapi/linux/jffs2.h
kernel/dma/contiguous.c
kernel/dma/direct.c
kernel/irq/irqdesc.c
kernel/kprobes.c
kernel/module.c
kernel/sched/core.c
kernel/sched/psi.c
kernel/signal.c
kernel/time/timekeeping.c
kernel/time/vsyscall.c
mm/huge_memory.c
mm/kasan/common.c
mm/memcontrol.c
mm/page_alloc.c
mm/z3fold.c
mm/zsmalloc.c
net/batman-adv/multicast.c
net/bluetooth/hci_core.c
net/bluetooth/hci_debugfs.c
net/bluetooth/hidp/core.c
net/bluetooth/l2cap_core.c
net/ceph/osd_client.c
net/core/sock.c
net/core/sock_diag.c
net/dsa/switch.c
net/ieee802154/6lowpan/reassembly.c
net/ipv4/inet_fragment.c
net/ipv4/ip_fragment.c
net/ipv4/tcp.c
net/ipv4/tcp_bpf.c
net/ipv4/tcp_output.c
net/ipv6/netfilter/nf_conntrack_reasm.c
net/ipv6/reassembly.c
net/netfilter/nf_conntrack_core.c
net/netfilter/nf_flow_table_core.c
net/netfilter/nf_flow_table_ip.c
net/netfilter/nf_tables_api.c
net/netfilter/nf_tables_offload.c
net/netfilter/nft_flow_offload.c
net/packet/af_packet.c
net/rxrpc/af_rxrpc.c
net/rxrpc/ar-internal.h
net/rxrpc/call_event.c
net/rxrpc/input.c
net/rxrpc/local_object.c
net/rxrpc/output.c
net/rxrpc/recvmsg.c
net/sched/act_skbedit.c
net/sched/sch_taprio.c
net/sctp/sm_sideeffect.c
net/sctp/stream.c
net/tipc/addr.c
net/tipc/link.c
net/tipc/msg.h
net/tls/tls_device.c
net/tls/tls_main.c
tools/bpf/bpftool/common.c
tools/hv/hv_kvp_daemon.c
tools/include/uapi/linux/bpf.h
tools/lib/bpf/libbpf.c
tools/power/acpi/tools/acpidump/apfiles.c
tools/testing/selftests/bpf/verifier/loops1.c
tools/testing/selftests/kvm/include/evmcs.h
tools/testing/selftests/kvm/lib/x86_64/processor.c
tools/testing/selftests/kvm/lib/x86_64/vmx.c
tools/testing/selftests/kvm/x86_64/evmcs_test.c
tools/testing/selftests/kvm/x86_64/hyperv_cpuid.c
tools/testing/selftests/kvm/x86_64/platform_info_test.c
tools/testing/selftests/kvm/x86_64/vmx_set_nested_state_test.c
tools/testing/selftests/net/tcp_fastopen_backup_key.sh
tools/testing/selftests/netfilter/nft_flowtable.sh
tools/testing/selftests/tc-testing/tc-tests/actions/skbedit.json
virt/kvm/arm/mmio.c
virt/kvm/arm/vgic/vgic-init.c

index f4c6121868c37d29b9efab6985f255c2593a1aad..6768305e4c266035682f58bc25ce20ee2ddc6a74 100644 (file)
@@ -9,7 +9,7 @@ Linux PCI Bus Subsystem
    :numbered:
 
    pci
-   picebus-howto
+   pciebus-howto
    pci-iov-howto
    msi-howto
    acpi-info
diff --git a/Documentation/PCI/pciebus-howto.rst b/Documentation/PCI/pciebus-howto.rst
new file mode 100644 (file)
index 0000000..f882ff6
--- /dev/null
@@ -0,0 +1,220 @@
+.. SPDX-License-Identifier: GPL-2.0
+.. include:: <isonum.txt>
+
+===========================================
+The PCI Express Port Bus Driver Guide HOWTO
+===========================================
+
+:Author: Tom L Nguyen tom.l.nguyen@intel.com 11/03/2004
+:Copyright: |copy| 2004 Intel Corporation
+
+About this guide
+================
+
+This guide describes the basics of the PCI Express Port Bus driver
+and provides information on how to enable the service drivers to
+register/unregister with the PCI Express Port Bus Driver.
+
+
+What is the PCI Express Port Bus Driver
+=======================================
+
+A PCI Express Port is a logical PCI-PCI Bridge structure. There
+are two types of PCI Express Port: the Root Port and the Switch
+Port. The Root Port originates a PCI Express link from a PCI Express
+Root Complex and the Switch Port connects PCI Express links to
+internal logical PCI buses. The Switch Port, which has its secondary
+bus representing the switch's internal routing logic, is called the
+switch's Upstream Port. The switch's Downstream Port is bridging from
+switch's internal routing bus to a bus representing the downstream
+PCI Express link from the PCI Express Switch.
+
+A PCI Express Port can provide up to four distinct functions,
+referred to in this document as services, depending on its port type.
+PCI Express Port's services include native hotplug support (HP),
+power management event support (PME), advanced error reporting
+support (AER), and virtual channel support (VC). These services may
+be handled by a single complex driver or be individually distributed
+and handled by corresponding service drivers.
+
+Why use the PCI Express Port Bus Driver?
+========================================
+
+In existing Linux kernels, the Linux Device Driver Model allows a
+physical device to be handled by only a single driver. The PCI
+Express Port is a PCI-PCI Bridge device with multiple distinct
+services. To maintain a clean and simple solution each service
+may have its own software service driver. In this case several
+service drivers will compete for a single PCI-PCI Bridge device.
+For example, if the PCI Express Root Port native hotplug service
+driver is loaded first, it claims a PCI-PCI Bridge Root Port. The
+kernel therefore does not load other service drivers for that Root
+Port. In other words, it is impossible to have multiple service
+drivers load and run on a PCI-PCI Bridge device simultaneously
+using the current driver model.
+
+To enable multiple service drivers running simultaneously requires
+having a PCI Express Port Bus driver, which manages all populated
+PCI Express Ports and distributes all provided service requests
+to the corresponding service drivers as required. Some key
+advantages of using the PCI Express Port Bus driver are listed below:
+
+  - Allow multiple service drivers to run simultaneously on
+    a PCI-PCI Bridge Port device.
+
+  - Allow service drivers implemented in an independent
+    staged approach.
+
+  - Allow one service driver to run on multiple PCI-PCI Bridge
+    Port devices.
+
+  - Manage and distribute resources of a PCI-PCI Bridge Port
+    device to requested service drivers.
+
+Configuring the PCI Express Port Bus Driver vs. Service Drivers
+===============================================================
+
+Including the PCI Express Port Bus Driver Support into the Kernel
+-----------------------------------------------------------------
+
+Including the PCI Express Port Bus driver depends on whether the PCI
+Express support is included in the kernel config. The kernel will
+automatically include the PCI Express Port Bus driver as a kernel
+driver when the PCI Express support is enabled in the kernel.
+
+Enabling Service Driver Support
+-------------------------------
+
+PCI device drivers are implemented based on Linux Device Driver Model.
+All service drivers are PCI device drivers. As discussed above, it is
+impossible to load any service driver once the kernel has loaded the
+PCI Express Port Bus Driver. To meet the PCI Express Port Bus Driver
+Model requires some minimal changes on existing service drivers that
+imposes no impact on the functionality of existing service drivers.
+
+A service driver is required to use the two APIs shown below to
+register its service with the PCI Express Port Bus driver (see
+section 5.2.1 & 5.2.2). It is important that a service driver
+initializes the pcie_port_service_driver data structure, included in
+header file /include/linux/pcieport_if.h, before calling these APIs.
+Failure to do so will result an identity mismatch, which prevents
+the PCI Express Port Bus driver from loading a service driver.
+
+pcie_port_service_register
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+::
+
+  int pcie_port_service_register(struct pcie_port_service_driver *new)
+
+This API replaces the Linux Driver Model's pci_register_driver API. A
+service driver should always calls pcie_port_service_register at
+module init. Note that after service driver being loaded, calls
+such as pci_enable_device(dev) and pci_set_master(dev) are no longer
+necessary since these calls are executed by the PCI Port Bus driver.
+
+pcie_port_service_unregister
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+::
+
+  void pcie_port_service_unregister(struct pcie_port_service_driver *new)
+
+pcie_port_service_unregister replaces the Linux Driver Model's
+pci_unregister_driver. It's always called by service driver when a
+module exits.
+
+Sample Code
+~~~~~~~~~~~
+
+Below is sample service driver code to initialize the port service
+driver data structure.
+::
+
+  static struct pcie_port_service_id service_id[] = { {
+    .vendor = PCI_ANY_ID,
+    .device = PCI_ANY_ID,
+    .port_type = PCIE_RC_PORT,
+    .service_type = PCIE_PORT_SERVICE_AER,
+    }, { /* end: all zeroes */ }
+  };
+
+  static struct pcie_port_service_driver root_aerdrv = {
+    .name              = (char *)device_name,
+    .id_table  = &service_id[0],
+
+    .probe             = aerdrv_load,
+    .remove            = aerdrv_unload,
+
+    .suspend   = aerdrv_suspend,
+    .resume            = aerdrv_resume,
+  };
+
+Below is a sample code for registering/unregistering a service
+driver.
+::
+
+  static int __init aerdrv_service_init(void)
+  {
+    int retval = 0;
+
+    retval = pcie_port_service_register(&root_aerdrv);
+    if (!retval) {
+      /*
+      * FIX ME
+      */
+    }
+    return retval;
+  }
+
+  static void __exit aerdrv_service_exit(void)
+  {
+    pcie_port_service_unregister(&root_aerdrv);
+  }
+
+  module_init(aerdrv_service_init);
+  module_exit(aerdrv_service_exit);
+
+Possible Resource Conflicts
+===========================
+
+Since all service drivers of a PCI-PCI Bridge Port device are
+allowed to run simultaneously, below lists a few of possible resource
+conflicts with proposed solutions.
+
+MSI and MSI-X Vector Resource
+-----------------------------
+
+Once MSI or MSI-X interrupts are enabled on a device, it stays in this
+mode until they are disabled again.  Since service drivers of the same
+PCI-PCI Bridge port share the same physical device, if an individual
+service driver enables or disables MSI/MSI-X mode it may result
+unpredictable behavior.
+
+To avoid this situation all service drivers are not permitted to
+switch interrupt mode on its device. The PCI Express Port Bus driver
+is responsible for determining the interrupt mode and this should be
+transparent to service drivers. Service drivers need to know only
+the vector IRQ assigned to the field irq of struct pcie_device, which
+is passed in when the PCI Express Port Bus driver probes each service
+driver. Service drivers should use (struct pcie_device*)dev->irq to
+call request_irq/free_irq. In addition, the interrupt mode is stored
+in the field interrupt_mode of struct pcie_device.
+
+PCI Memory/IO Mapped Regions
+----------------------------
+
+Service drivers for PCI Express Power Management (PME), Advanced
+Error Reporting (AER), Hot-Plug (HP) and Virtual Channel (VC) access
+PCI configuration space on the PCI Express port. In all cases the
+registers accessed are independent of each other. This patch assumes
+that all service drivers will be well behaved and not overwrite
+other service driver's configuration settings.
+
+PCI Config Registers
+--------------------
+
+Each service driver runs its PCI config operations on its own
+capability structure except the PCI Express capability structure, in
+which Root Control register and Device Control register are shared
+between PME and AER. This patch assumes that all service drivers
+will be well behaved and not overwrite other service driver's
+configuration settings.
diff --git a/Documentation/PCI/picebus-howto.rst b/Documentation/PCI/picebus-howto.rst
deleted file mode 100644 (file)
index f882ff6..0000000
+++ /dev/null
@@ -1,220 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0
-.. include:: <isonum.txt>
-
-===========================================
-The PCI Express Port Bus Driver Guide HOWTO
-===========================================
-
-:Author: Tom L Nguyen tom.l.nguyen@intel.com 11/03/2004
-:Copyright: |copy| 2004 Intel Corporation
-
-About this guide
-================
-
-This guide describes the basics of the PCI Express Port Bus driver
-and provides information on how to enable the service drivers to
-register/unregister with the PCI Express Port Bus Driver.
-
-
-What is the PCI Express Port Bus Driver
-=======================================
-
-A PCI Express Port is a logical PCI-PCI Bridge structure. There
-are two types of PCI Express Port: the Root Port and the Switch
-Port. The Root Port originates a PCI Express link from a PCI Express
-Root Complex and the Switch Port connects PCI Express links to
-internal logical PCI buses. The Switch Port, which has its secondary
-bus representing the switch's internal routing logic, is called the
-switch's Upstream Port. The switch's Downstream Port is bridging from
-switch's internal routing bus to a bus representing the downstream
-PCI Express link from the PCI Express Switch.
-
-A PCI Express Port can provide up to four distinct functions,
-referred to in this document as services, depending on its port type.
-PCI Express Port's services include native hotplug support (HP),
-power management event support (PME), advanced error reporting
-support (AER), and virtual channel support (VC). These services may
-be handled by a single complex driver or be individually distributed
-and handled by corresponding service drivers.
-
-Why use the PCI Express Port Bus Driver?
-========================================
-
-In existing Linux kernels, the Linux Device Driver Model allows a
-physical device to be handled by only a single driver. The PCI
-Express Port is a PCI-PCI Bridge device with multiple distinct
-services. To maintain a clean and simple solution each service
-may have its own software service driver. In this case several
-service drivers will compete for a single PCI-PCI Bridge device.
-For example, if the PCI Express Root Port native hotplug service
-driver is loaded first, it claims a PCI-PCI Bridge Root Port. The
-kernel therefore does not load other service drivers for that Root
-Port. In other words, it is impossible to have multiple service
-drivers load and run on a PCI-PCI Bridge device simultaneously
-using the current driver model.
-
-To enable multiple service drivers running simultaneously requires
-having a PCI Express Port Bus driver, which manages all populated
-PCI Express Ports and distributes all provided service requests
-to the corresponding service drivers as required. Some key
-advantages of using the PCI Express Port Bus driver are listed below:
-
-  - Allow multiple service drivers to run simultaneously on
-    a PCI-PCI Bridge Port device.
-
-  - Allow service drivers implemented in an independent
-    staged approach.
-
-  - Allow one service driver to run on multiple PCI-PCI Bridge
-    Port devices.
-
-  - Manage and distribute resources of a PCI-PCI Bridge Port
-    device to requested service drivers.
-
-Configuring the PCI Express Port Bus Driver vs. Service Drivers
-===============================================================
-
-Including the PCI Express Port Bus Driver Support into the Kernel
------------------------------------------------------------------
-
-Including the PCI Express Port Bus driver depends on whether the PCI
-Express support is included in the kernel config. The kernel will
-automatically include the PCI Express Port Bus driver as a kernel
-driver when the PCI Express support is enabled in the kernel.
-
-Enabling Service Driver Support
--------------------------------
-
-PCI device drivers are implemented based on Linux Device Driver Model.
-All service drivers are PCI device drivers. As discussed above, it is
-impossible to load any service driver once the kernel has loaded the
-PCI Express Port Bus Driver. To meet the PCI Express Port Bus Driver
-Model requires some minimal changes on existing service drivers that
-imposes no impact on the functionality of existing service drivers.
-
-A service driver is required to use the two APIs shown below to
-register its service with the PCI Express Port Bus driver (see
-section 5.2.1 & 5.2.2). It is important that a service driver
-initializes the pcie_port_service_driver data structure, included in
-header file /include/linux/pcieport_if.h, before calling these APIs.
-Failure to do so will result an identity mismatch, which prevents
-the PCI Express Port Bus driver from loading a service driver.
-
-pcie_port_service_register
-~~~~~~~~~~~~~~~~~~~~~~~~~~
-::
-
-  int pcie_port_service_register(struct pcie_port_service_driver *new)
-
-This API replaces the Linux Driver Model's pci_register_driver API. A
-service driver should always calls pcie_port_service_register at
-module init. Note that after service driver being loaded, calls
-such as pci_enable_device(dev) and pci_set_master(dev) are no longer
-necessary since these calls are executed by the PCI Port Bus driver.
-
-pcie_port_service_unregister
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-::
-
-  void pcie_port_service_unregister(struct pcie_port_service_driver *new)
-
-pcie_port_service_unregister replaces the Linux Driver Model's
-pci_unregister_driver. It's always called by service driver when a
-module exits.
-
-Sample Code
-~~~~~~~~~~~
-
-Below is sample service driver code to initialize the port service
-driver data structure.
-::
-
-  static struct pcie_port_service_id service_id[] = { {
-    .vendor = PCI_ANY_ID,
-    .device = PCI_ANY_ID,
-    .port_type = PCIE_RC_PORT,
-    .service_type = PCIE_PORT_SERVICE_AER,
-    }, { /* end: all zeroes */ }
-  };
-
-  static struct pcie_port_service_driver root_aerdrv = {
-    .name              = (char *)device_name,
-    .id_table  = &service_id[0],
-
-    .probe             = aerdrv_load,
-    .remove            = aerdrv_unload,
-
-    .suspend   = aerdrv_suspend,
-    .resume            = aerdrv_resume,
-  };
-
-Below is a sample code for registering/unregistering a service
-driver.
-::
-
-  static int __init aerdrv_service_init(void)
-  {
-    int retval = 0;
-
-    retval = pcie_port_service_register(&root_aerdrv);
-    if (!retval) {
-      /*
-      * FIX ME
-      */
-    }
-    return retval;
-  }
-
-  static void __exit aerdrv_service_exit(void)
-  {
-    pcie_port_service_unregister(&root_aerdrv);
-  }
-
-  module_init(aerdrv_service_init);
-  module_exit(aerdrv_service_exit);
-
-Possible Resource Conflicts
-===========================
-
-Since all service drivers of a PCI-PCI Bridge Port device are
-allowed to run simultaneously, below lists a few of possible resource
-conflicts with proposed solutions.
-
-MSI and MSI-X Vector Resource
------------------------------
-
-Once MSI or MSI-X interrupts are enabled on a device, it stays in this
-mode until they are disabled again.  Since service drivers of the same
-PCI-PCI Bridge port share the same physical device, if an individual
-service driver enables or disables MSI/MSI-X mode it may result
-unpredictable behavior.
-
-To avoid this situation all service drivers are not permitted to
-switch interrupt mode on its device. The PCI Express Port Bus driver
-is responsible for determining the interrupt mode and this should be
-transparent to service drivers. Service drivers need to know only
-the vector IRQ assigned to the field irq of struct pcie_device, which
-is passed in when the PCI Express Port Bus driver probes each service
-driver. Service drivers should use (struct pcie_device*)dev->irq to
-call request_irq/free_irq. In addition, the interrupt mode is stored
-in the field interrupt_mode of struct pcie_device.
-
-PCI Memory/IO Mapped Regions
-----------------------------
-
-Service drivers for PCI Express Power Management (PME), Advanced
-Error Reporting (AER), Hot-Plug (HP) and Virtual Channel (VC) access
-PCI configuration space on the PCI Express port. In all cases the
-registers accessed are independent of each other. This patch assumes
-that all service drivers will be well behaved and not overwrite
-other service driver's configuration settings.
-
-PCI Config Registers
---------------------
-
-Each service driver runs its PCI config operations on its own
-capability structure except the PCI Express capability structure, in
-which Root Control register and Device Control register are shared
-between PME and AER. This patch assumes that all service drivers
-will be well behaved and not overwrite other service driver's
-configuration settings.
index 47d981a86e2f8a5c2115d1834eda3ab7af5ccaae..4c1971960afa30484cfe0d2533e9cf28d003662c 100644 (file)
                        Run specified binary instead of /init from the ramdisk,
                        used for early userspace startup. See initrd.
 
+       rdrand=         [X86]
+                       force - Override the decision by the kernel to hide the
+                               advertisement of RDRAND support (this affects
+                               certain AMD processors because of buggy BIOS
+                               support, specifically around the suspend/resume
+                               path).
+
        rdt=            [HW,X86,RDT]
                        Turn on/off individual RDT features. List is:
                        cmt, mbmtotal, mbmlocal, l3cat, l3cdp, l2cat, l2cdp,
index a7d44e71019d680f283b2e7bcbe25e59e079c1bb..287b98708a40915a80ba76455621b507cce161bd 100644 (file)
@@ -39,7 +39,6 @@ Table : Subdirectories in /proc/sys/net
  802       E802 protocol         ax25       AX25
  ethernet  Ethernet protocol     rose       X.25 PLP layer
  ipv4      IP version 4          x25        X.25 protocol
- ipx       IPX                   token-ring IBM token ring
  bridge    Bridging              decnet     DEC net
  ipv6      IP version 6          tipc       TIPC
  ========= =================== = ========== ==================
@@ -401,33 +400,7 @@ interface.
 (network) that the route leads to, the router (may be directly connected), the
 route flags, and the device the route is using.
 
-
-5. IPX
-------
-
-The IPX protocol has no tunable values in proc/sys/net.
-
-The IPX  protocol  does,  however,  provide  proc/net/ipx. This lists each IPX
-socket giving  the  local  and  remote  addresses  in  Novell  format (that is
-network:node:port). In  accordance  with  the  strange  Novell  tradition,
-everything but the port is in hex. Not_Connected is displayed for sockets that
-are not  tied to a specific remote address. The Tx and Rx queue sizes indicate
-the number  of  bytes  pending  for  transmission  and  reception.  The  state
-indicates the  state  the  socket  is  in and the uid is the owning uid of the
-socket.
-
-The /proc/net/ipx_interface  file lists all IPX interfaces. For each interface
-it gives  the network number, the node number, and indicates if the network is
-the primary  network.  It  also  indicates  which  device  it  is bound to (or
-Internal for  internal  networks)  and  the  Frame  Type if appropriate. Linux
-supports 802.3,  802.2,  802.2  SNAP  and DIX (Blue Book) ethernet framing for
-IPX.
-
-The /proc/net/ipx_route  table  holds  a list of IPX routes. For each route it
-gives the  destination  network, the router node (or Directly) and the network
-address of the router (or Connected) for internal networks.
-
-6. TIPC
+5. TIPC
 -------
 
 tipc_rmem
index b70b70dc4524d4524ce1a744b0286eafade8afdc..0dd3f748239f2858f49ec24590433ea3c8843230 100644 (file)
@@ -506,21 +506,3 @@ Drivers should ignore the changes to TLS the device feature flags.
 These flags will be acted upon accordingly by the core ``ktls`` code.
 TLS device feature flags only control adding of new TLS connection
 offloads, old connections will remain active after flags are cleared.
-
-Known bugs
-==========
-
-skb_orphan() leaks clear text
------------------------------
-
-Currently drivers depend on the :c:member:`sk` member of
-:c:type:`struct sk_buff <sk_buff>` to identify segments requiring
-encryption. Any operation which removes or does not preserve the socket
-association such as :c:func:`skb_orphan` or :c:func:`skb_clone`
-will cause the driver to miss the packets and lead to clear text leaks.
-
-Redirects leak clear text
--------------------------
-
-In the RX direction, if segment has already been decrypted by the device
-and it gets redirected or mirrored - clear text will be transmitted out.
index 949d5dcdd9a348fd646f89c62f604d9d29433d2c..0104830d5075ff255b539c34adabfb6b70f7ea45 100644 (file)
@@ -204,8 +204,8 @@ Ethernet device, which instead of receiving packets from a physical
 media, receives them from user space program and instead of sending 
 packets via physical media sends them to the user space program. 
 
-Let's say that you configured IPX on the tap0, then whenever 
-the kernel sends an IPX packet to tap0, it is passed to the application
+Let's say that you configured IPv6 on the tap0, then whenever
+the kernel sends an IPv6 packet to tap0, it is passed to the application
 (VTun for example). The application encrypts, compresses and sends it to 
 the other side over TCP or UDP. The application on the other side decompresses
 and decrypts the data received and writes the packet to the TAP device, 
index 43604d6ab96c2b6c9f989eea100d249bad2f8881..9cbcf167bdd08f94bfeb80aa7424c5893224555c 100644 (file)
@@ -183,7 +183,7 @@ M:  Realtek linux nic maintainers <nic_swsd@realtek.com>
 M:     Heiner Kallweit <hkallweit1@gmail.com>
 L:     netdev@vger.kernel.org
 S:     Maintained
-F:     drivers/net/ethernet/realtek/r8169.c
+F:     drivers/net/ethernet/realtek/r8169*
 
 8250/16?50 (AND CLONE UARTS) SERIAL DRIVER
 M:     Greg Kroah-Hartman <gregkh@linuxfoundation.org>
@@ -6065,7 +6065,7 @@ M:        Florian Fainelli <f.fainelli@gmail.com>
 M:     Heiner Kallweit <hkallweit1@gmail.com>
 L:     netdev@vger.kernel.org
 S:     Maintained
-F:     Documentation/ABI/testing/sysfs-bus-mdio
+F:     Documentation/ABI/testing/sysfs-class-net-phydev
 F:     Documentation/devicetree/bindings/net/ethernet-phy.yaml
 F:     Documentation/devicetree/bindings/net/mdio*
 F:     Documentation/networking/phy.rst
@@ -8832,14 +8832,6 @@ F:       virt/kvm/*
 F:     tools/kvm/
 F:     tools/testing/selftests/kvm/
 
-KERNEL VIRTUAL MACHINE FOR AMD-V (KVM/amd)
-M:     Joerg Roedel <joro@8bytes.org>
-L:     kvm@vger.kernel.org
-W:     http://www.linux-kvm.org/
-S:     Maintained
-F:     arch/x86/include/asm/svm.h
-F:     arch/x86/kvm/svm.c
-
 KERNEL VIRTUAL MACHINE FOR ARM/ARM64 (KVM/arm, KVM/arm64)
 M:     Marc Zyngier <maz@kernel.org>
 R:     James Morse <james.morse@arm.com>
@@ -8882,7 +8874,7 @@ M:        Christian Borntraeger <borntraeger@de.ibm.com>
 M:     Janosch Frank <frankja@linux.ibm.com>
 R:     David Hildenbrand <david@redhat.com>
 R:     Cornelia Huck <cohuck@redhat.com>
-L:     linux-s390@vger.kernel.org
+L:     kvm@vger.kernel.org
 W:     http://www.ibm.com/developerworks/linux/linux390/
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/kvms390/linux.git
 S:     Supported
@@ -8897,6 +8889,11 @@ F:       tools/testing/selftests/kvm/*/s390x/
 KERNEL VIRTUAL MACHINE FOR X86 (KVM/x86)
 M:     Paolo Bonzini <pbonzini@redhat.com>
 M:     Radim Krčmář <rkrcmar@redhat.com>
+R:     Sean Christopherson <sean.j.christopherson@intel.com>
+R:     Vitaly Kuznetsov <vkuznets@redhat.com>
+R:     Wanpeng Li <wanpengli@tencent.com>
+R:     Jim Mattson <jmattson@google.com>
+R:     Joerg Roedel <joro@8bytes.org>
 L:     kvm@vger.kernel.org
 W:     http://www.linux-kvm.org
 T:     git git://git.kernel.org/pub/scm/virt/kvm/kvm.git
@@ -8904,8 +8901,12 @@ S:       Supported
 F:     arch/x86/kvm/
 F:     arch/x86/kvm/*/
 F:     arch/x86/include/uapi/asm/kvm*
+F:     arch/x86/include/uapi/asm/vmx.h
+F:     arch/x86/include/uapi/asm/svm.h
 F:     arch/x86/include/asm/kvm*
 F:     arch/x86/include/asm/pvclock-abi.h
+F:     arch/x86/include/asm/svm.h
+F:     arch/x86/include/asm/vmx.h
 F:     arch/x86/kernel/kvm.c
 F:     arch/x86/kernel/kvmclock.c
 
@@ -14882,9 +14883,9 @@ F:      include/linux/arm_sdei.h
 F:     include/uapi/linux/arm_sdei.h
 
 SOFTWARE RAID (Multiple Disks) SUPPORT
-M:     Shaohua Li <shli@kernel.org>
+M:     Song Liu <song@kernel.org>
 L:     linux-raid@vger.kernel.org
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/shli/md.git
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/song/md.git
 S:     Supported
 F:     drivers/md/Makefile
 F:     drivers/md/Kconfig
index 9fa18613566f468d6345cf505a8102898f2b9536..f125625efd6013efa2873b7f72d2bc073bba37a1 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@
 VERSION = 5
 PATCHLEVEL = 3
 SUBLEVEL = 0
-EXTRAVERSION = -rc5
+EXTRAVERSION = -rc6
 NAME = Bobtail Squid
 
 # *DOCUMENTATION*
index 33b00579befff2d4ea0809965398f67cedb6fc77..24360211534abe47a053dbc575c6e46c49e3c734 100644 (file)
@@ -7,6 +7,8 @@ config ARM
        select ARCH_HAS_BINFMT_FLAT
        select ARCH_HAS_DEBUG_VIRTUAL if MMU
        select ARCH_HAS_DEVMEM_IS_ALLOWED
+       select ARCH_HAS_DMA_COHERENT_TO_PFN if SWIOTLB
+       select ARCH_HAS_DMA_MMAP_PGPROT if SWIOTLB
        select ARCH_HAS_ELF_RANDOMIZE
        select ARCH_HAS_FORTIFY_SOURCE
        select ARCH_HAS_KEEPINITRD
@@ -18,6 +20,8 @@ config ARM
        select ARCH_HAS_SET_MEMORY
        select ARCH_HAS_STRICT_KERNEL_RWX if MMU && !XIP_KERNEL
        select ARCH_HAS_STRICT_MODULE_RWX if MMU
+       select ARCH_HAS_SYNC_DMA_FOR_DEVICE if SWIOTLB
+       select ARCH_HAS_SYNC_DMA_FOR_CPU if SWIOTLB
        select ARCH_HAS_TEARDOWN_DMA_OPS if MMU
        select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
        select ARCH_HAVE_CUSTOM_GPIO_H
index 0ce56ad754ceb33655a467138ed9b36d3448991d..ea2c84214bac18a18e03475e48a765156f72e6fa 100644 (file)
@@ -46,6 +46,7 @@ static int __init parse_tag_acorn(const struct tag *tag)
        switch (tag->u.acorn.vram_pages) {
        case 512:
                vram_size += PAGE_SIZE * 256;
+               /* Fall through - ??? */
        case 256:
                vram_size += PAGE_SIZE * 256;
        default:
index c54cd7ed90ba5e6a8d64377ef96b19fd4cad9386..c1222c0e9fd3bebb6a64f209e80e8d924375d041 100644 (file)
@@ -664,10 +664,6 @@ config ARM_LPAE
                !CPU_32v4 && !CPU_32v3
        select PHYS_ADDR_T_64BIT
        select SWIOTLB
-       select ARCH_HAS_DMA_COHERENT_TO_PFN
-       select ARCH_HAS_DMA_MMAP_PGPROT
-       select ARCH_HAS_SYNC_DMA_FOR_DEVICE
-       select ARCH_HAS_SYNC_DMA_FOR_CPU
        help
          Say Y if you have an ARMv7 processor supporting the LPAE page
          table format and you would like to access memory beyond the
index 52cf96ea43e5dfdba220101d5f1f6eef64875148..cbc7cdae1c6a43220cb1c7a4f0f34d779065180e 100644 (file)
@@ -46,6 +46,7 @@ static inline uint64_t CVMX_SLI_PCIE_MSI_RCV_FUNC(void)
        case OCTEON_CN78XX & OCTEON_FAMILY_MASK:
                if (OCTEON_IS_MODEL(OCTEON_CN78XX_PASS1_X))
                        return 0x0000000000003CB0ull;
+               /* Else, fall through */
        default:
                return 0x0000000000023CB0ull;
        }
index a39b079e73f25758e184b0acf20209b4fe6fb8f0..6d58c1739b4239619095fe181431cdf7eaa2d4b5 100644 (file)
@@ -2,6 +2,7 @@
 #ifndef _PARISC_PGTABLE_H
 #define _PARISC_PGTABLE_H
 
+#include <asm/page.h>
 #include <asm-generic/4level-fixup.h>
 
 #include <asm/fixmap.h>
@@ -98,8 +99,6 @@ static inline void purge_tlb_entries(struct mm_struct *mm, unsigned long addr)
 
 #endif /* !__ASSEMBLY__ */
 
-#include <asm/page.h>
-
 #define pte_ERROR(e) \
        printk("%s:%d: bad pte %08lx.\n", __FILE__, __LINE__, pte_val(e))
 #define pmd_ERROR(e) \
index 8574338bf23ba48394fd40a49a564bf11969868e..9991ec2371e44e21626df7b587f486c18dc4641d 100644 (file)
@@ -34,10 +34,13 @@ static inline void time_travel_set_time(unsigned long long ns)
        time_travel_time = ns;
 }
 
-static inline void time_travel_set_timer(enum time_travel_timer_mode mode,
-                                        unsigned long long expiry)
+static inline void time_travel_set_timer_mode(enum time_travel_timer_mode mode)
 {
        time_travel_timer_mode = mode;
+}
+
+static inline void time_travel_set_timer_expiry(unsigned long long expiry)
+{
        time_travel_timer_expiry = expiry;
 }
 #else
@@ -50,8 +53,11 @@ static inline void time_travel_set_time(unsigned long long ns)
 {
 }
 
-static inline void time_travel_set_timer(enum time_travel_timer_mode mode,
-                                        unsigned long long expiry)
+static inline void time_travel_set_timer_mode(enum time_travel_timer_mode mode)
+{
+}
+
+static inline void time_travel_set_timer_expiry(unsigned long long expiry)
 {
 }
 
index 67c0d1a860e980d97ecb6d6bbf7cb349699edbfc..6bede7888fc202f1a268ffcab0f763219a9fba5d 100644 (file)
@@ -213,7 +213,7 @@ static void time_travel_sleep(unsigned long long duration)
        if (time_travel_timer_mode != TT_TMR_DISABLED ||
            time_travel_timer_expiry < next) {
                if (time_travel_timer_mode == TT_TMR_ONESHOT)
-                       time_travel_set_timer(TT_TMR_DISABLED, 0);
+                       time_travel_set_timer_mode(TT_TMR_DISABLED);
                /*
                 * time_travel_time will be adjusted in the timer
                 * IRQ handler so it works even when the signal
index 6a051b078359dd99a4c98fdcea8daa3394da3314..234757233355fb1278bac9f98dca9c0bc637ea46 100644 (file)
@@ -50,7 +50,7 @@ void timer_handler(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs)
 static int itimer_shutdown(struct clock_event_device *evt)
 {
        if (time_travel_mode != TT_MODE_OFF)
-               time_travel_set_timer(TT_TMR_DISABLED, 0);
+               time_travel_set_timer_mode(TT_TMR_DISABLED);
 
        if (time_travel_mode != TT_MODE_INFCPU)
                os_timer_disable();
@@ -62,9 +62,10 @@ static int itimer_set_periodic(struct clock_event_device *evt)
 {
        unsigned long long interval = NSEC_PER_SEC / HZ;
 
-       if (time_travel_mode != TT_MODE_OFF)
-               time_travel_set_timer(TT_TMR_PERIODIC,
-                                     time_travel_time + interval);
+       if (time_travel_mode != TT_MODE_OFF) {
+               time_travel_set_timer_mode(TT_TMR_PERIODIC);
+               time_travel_set_timer_expiry(time_travel_time + interval);
+       }
 
        if (time_travel_mode != TT_MODE_INFCPU)
                os_timer_set_interval(interval);
@@ -77,9 +78,10 @@ static int itimer_next_event(unsigned long delta,
 {
        delta += 1;
 
-       if (time_travel_mode != TT_MODE_OFF)
-               time_travel_set_timer(TT_TMR_ONESHOT,
-                                     time_travel_time + delta);
+       if (time_travel_mode != TT_MODE_OFF) {
+               time_travel_set_timer_mode(TT_TMR_ONESHOT);
+               time_travel_set_timer_expiry(time_travel_time + delta);
+       }
 
        if (time_travel_mode != TT_MODE_INFCPU)
                return os_timer_one_shot(delta);
index 5f2d03067ae57cdb95555fe423bdafc52bbec200..2faddeb0398afff4bd24228bbaededb18893c976 100644 (file)
@@ -72,6 +72,8 @@ static unsigned long find_trampoline_placement(void)
 
        /* Find the first usable memory region under bios_start. */
        for (i = boot_params->e820_entries - 1; i >= 0; i--) {
+               unsigned long new;
+
                entry = &boot_params->e820_table[i];
 
                /* Skip all entries above bios_start. */
@@ -84,15 +86,20 @@ static unsigned long find_trampoline_placement(void)
 
                /* Adjust bios_start to the end of the entry if needed. */
                if (bios_start > entry->addr + entry->size)
-                       bios_start = entry->addr + entry->size;
+                       new = entry->addr + entry->size;
 
                /* Keep bios_start page-aligned. */
-               bios_start = round_down(bios_start, PAGE_SIZE);
+               new = round_down(new, PAGE_SIZE);
 
                /* Skip the entry if it's too small. */
-               if (bios_start - TRAMPOLINE_32BIT_SIZE < entry->addr)
+               if (new - TRAMPOLINE_32BIT_SIZE < entry->addr)
                        continue;
 
+               /* Protect against underflow. */
+               if (new - TRAMPOLINE_32BIT_SIZE > bios_start)
+                       break;
+
+               bios_start = new;
                break;
        }
 
index 81b005e4c7d9f956e632b82cef9302976fc73e6c..325959d19d9a859b0f153d9c3a09ec9fe54833a2 100644 (file)
@@ -1236,7 +1236,7 @@ void x86_pmu_enable_event(struct perf_event *event)
  * Add a single event to the PMU.
  *
  * The event is added to the group of enabled events
- * but only if it can be scehduled with existing events.
+ * but only if it can be scheduled with existing events.
  */
 static int x86_pmu_add(struct perf_event *event, int flags)
 {
index f5e90a849bca6c1ab6493d03b0d7ad76a69086f9..9e5f3c722c338dc116f8200b726de8d0167507c3 100644 (file)
@@ -59,7 +59,6 @@ static void sanitize_boot_params(struct boot_params *boot_params)
                        BOOT_PARAM_PRESERVE(apm_bios_info),
                        BOOT_PARAM_PRESERVE(tboot_addr),
                        BOOT_PARAM_PRESERVE(ist_info),
-                       BOOT_PARAM_PRESERVE(acpi_rsdp_addr),
                        BOOT_PARAM_PRESERVE(hd0_info),
                        BOOT_PARAM_PRESERVE(hd1_info),
                        BOOT_PARAM_PRESERVE(sys_desc_table),
@@ -71,6 +70,7 @@ static void sanitize_boot_params(struct boot_params *boot_params)
                        BOOT_PARAM_PRESERVE(eddbuf_entries),
                        BOOT_PARAM_PRESERVE(edd_mbr_sig_buf_entries),
                        BOOT_PARAM_PRESERVE(edd_mbr_sig_buffer),
+                       BOOT_PARAM_PRESERVE(hdr),
                        BOOT_PARAM_PRESERVE(e820_table),
                        BOOT_PARAM_PRESERVE(eddbuf),
                };
index 0278aa66ef6274eeb91eedf1dfe7d10d60f2d4f2..fe7c205233f1cbb8fcccb7ec413c9322a19cc94c 100644 (file)
  * While adding a new CPUID for a new microarchitecture, add a new
  * group to keep logically sorted out in chronological order. Within
  * that group keep the CPUID for the variants sorted by model number.
+ *
+ * The defined symbol names have the following form:
+ *     INTEL_FAM6{OPTFAMILY}_{MICROARCH}{OPTDIFF}
+ * where:
+ * OPTFAMILY   Describes the family of CPUs that this belongs to. Default
+ *             is assumed to be "_CORE" (and should be omitted). Other values
+ *             currently in use are _ATOM and _XEON_PHI
+ * MICROARCH   Is the code name for the micro-architecture for this core.
+ *             N.B. Not the platform name.
+ * OPTDIFF     If needed, a short string to differentiate by market segment.
+ *             Exact strings here will vary over time. _DESKTOP, _MOBILE, and
+ *             _X (short for Xeon server) should be used when they are
+ *             appropriate.
+ *
+ * The #define line may optionally include a comment including platform names.
  */
 
 #define INTEL_FAM6_CORE_YONAH          0x0E
index 6b4fc2788078d7c5add77acd65af094cc1230543..271d837d69a8868118d811dabaa5739d482c2c0c 100644 (file)
 #define MSR_AMD64_PATCH_LEVEL          0x0000008b
 #define MSR_AMD64_TSC_RATIO            0xc0000104
 #define MSR_AMD64_NB_CFG               0xc001001f
+#define MSR_AMD64_CPUID_FN_1           0xc0011004
 #define MSR_AMD64_PATCH_LOADER         0xc0010020
 #define MSR_AMD64_OSVW_ID_LENGTH       0xc0010140
 #define MSR_AMD64_OSVW_STATUS          0xc0010141
index 109f974f983532041ab48e020e1fda9d5539f8f5..80bc209c07081b73dfab7c7632829db3d1e47bff 100644 (file)
        "       lfence;\n"                                      \
        "       jmp    902b;\n"                                 \
        "       .align 16\n"                                    \
-       "903:   addl   $4, %%esp;\n"                            \
+       "903:   lea    4(%%esp), %%esp;\n"                      \
        "       pushl  %[thunk_target];\n"                      \
        "       ret;\n"                                         \
        "       .align 16\n"                                    \
index f5291362da1ad72877aa8d9f7bcf621a83e5c1f4..aa5495d0f47832fbc02d102a8fb66180a550b6e9 100644 (file)
@@ -722,7 +722,7 @@ static __initdata unsigned long lapic_cal_pm1, lapic_cal_pm2;
 static __initdata unsigned long lapic_cal_j1, lapic_cal_j2;
 
 /*
- * Temporary interrupt handler.
+ * Temporary interrupt handler and polled calibration function.
  */
 static void __init lapic_cal_handler(struct clock_event_device *dev)
 {
@@ -851,7 +851,8 @@ bool __init apic_needs_pit(void)
 static int __init calibrate_APIC_clock(void)
 {
        struct clock_event_device *levt = this_cpu_ptr(&lapic_events);
-       void (*real_handler)(struct clock_event_device *dev);
+       u64 tsc_perj = 0, tsc_start = 0;
+       unsigned long jif_start;
        unsigned long deltaj;
        long delta, deltatsc;
        int pm_referenced = 0;
@@ -878,28 +879,64 @@ static int __init calibrate_APIC_clock(void)
        apic_printk(APIC_VERBOSE, "Using local APIC timer interrupts.\n"
                    "calibrating APIC timer ...\n");
 
+       /*
+        * There are platforms w/o global clockevent devices. Instead of
+        * making the calibration conditional on that, use a polling based
+        * approach everywhere.
+        */
        local_irq_disable();
 
-       /* Replace the global interrupt handler */
-       real_handler = global_clock_event->event_handler;
-       global_clock_event->event_handler = lapic_cal_handler;
-
        /*
         * Setup the APIC counter to maximum. There is no way the lapic
         * can underflow in the 100ms detection time frame
         */
        __setup_APIC_LVTT(0xffffffff, 0, 0);
 
-       /* Let the interrupts run */
+       /*
+        * Methods to terminate the calibration loop:
+        *  1) Global clockevent if available (jiffies)
+        *  2) TSC if available and frequency is known
+        */
+       jif_start = READ_ONCE(jiffies);
+
+       if (tsc_khz) {
+               tsc_start = rdtsc();
+               tsc_perj = div_u64((u64)tsc_khz * 1000, HZ);
+       }
+
+       /*
+        * Enable interrupts so the tick can fire, if a global
+        * clockevent device is available
+        */
        local_irq_enable();
 
-       while (lapic_cal_loops <= LAPIC_CAL_LOOPS)
-               cpu_relax();
+       while (lapic_cal_loops <= LAPIC_CAL_LOOPS) {
+               /* Wait for a tick to elapse */
+               while (1) {
+                       if (tsc_khz) {
+                               u64 tsc_now = rdtsc();
+                               if ((tsc_now - tsc_start) >= tsc_perj) {
+                                       tsc_start += tsc_perj;
+                                       break;
+                               }
+                       } else {
+                               unsigned long jif_now = READ_ONCE(jiffies);
 
-       local_irq_disable();
+                               if (time_after(jif_now, jif_start)) {
+                                       jif_start = jif_now;
+                                       break;
+                               }
+                       }
+                       cpu_relax();
+               }
 
-       /* Restore the real event handler */
-       global_clock_event->event_handler = real_handler;
+               /* Invoke the calibration routine */
+               local_irq_disable();
+               lapic_cal_handler(NULL);
+               local_irq_enable();
+       }
+
+       local_irq_disable();
 
        /* Build delta t1-t2 as apic timer counts down */
        delta = lapic_cal_t1 - lapic_cal_t2;
@@ -943,10 +980,11 @@ static int __init calibrate_APIC_clock(void)
        levt->features &= ~CLOCK_EVT_FEAT_DUMMY;
 
        /*
-        * PM timer calibration failed or not turned on
-        * so lets try APIC timer based calibration
+        * PM timer calibration failed or not turned on so lets try APIC
+        * timer based calibration, if a global clockevent device is
+        * available.
         */
-       if (!pm_referenced) {
+       if (!pm_referenced && global_clock_event) {
                apic_printk(APIC_VERBOSE, "... verify APIC timer\n");
 
                /*
index 8d4e50428b684783310f5420dbe7d03751f9f464..68c363c341bf2a3794ec26f29df4dd28281d4dc5 100644 (file)
@@ -804,6 +804,64 @@ static void init_amd_ln(struct cpuinfo_x86 *c)
        msr_set_bit(MSR_AMD64_DE_CFG, 31);
 }
 
+static bool rdrand_force;
+
+static int __init rdrand_cmdline(char *str)
+{
+       if (!str)
+               return -EINVAL;
+
+       if (!strcmp(str, "force"))
+               rdrand_force = true;
+       else
+               return -EINVAL;
+
+       return 0;
+}
+early_param("rdrand", rdrand_cmdline);
+
+static void clear_rdrand_cpuid_bit(struct cpuinfo_x86 *c)
+{
+       /*
+        * Saving of the MSR used to hide the RDRAND support during
+        * suspend/resume is done by arch/x86/power/cpu.c, which is
+        * dependent on CONFIG_PM_SLEEP.
+        */
+       if (!IS_ENABLED(CONFIG_PM_SLEEP))
+               return;
+
+       /*
+        * The nordrand option can clear X86_FEATURE_RDRAND, so check for
+        * RDRAND support using the CPUID function directly.
+        */
+       if (!(cpuid_ecx(1) & BIT(30)) || rdrand_force)
+               return;
+
+       msr_clear_bit(MSR_AMD64_CPUID_FN_1, 62);
+
+       /*
+        * Verify that the CPUID change has occurred in case the kernel is
+        * running virtualized and the hypervisor doesn't support the MSR.
+        */
+       if (cpuid_ecx(1) & BIT(30)) {
+               pr_info_once("BIOS may not properly restore RDRAND after suspend, but hypervisor does not support hiding RDRAND via CPUID.\n");
+               return;
+       }
+
+       clear_cpu_cap(c, X86_FEATURE_RDRAND);
+       pr_info_once("BIOS may not properly restore RDRAND after suspend, hiding RDRAND via CPUID. Use rdrand=force to reenable.\n");
+}
+
+static void init_amd_jg(struct cpuinfo_x86 *c)
+{
+       /*
+        * Some BIOS implementations do not restore proper RDRAND support
+        * across suspend and resume. Check on whether to hide the RDRAND
+        * instruction support via CPUID.
+        */
+       clear_rdrand_cpuid_bit(c);
+}
+
 static void init_amd_bd(struct cpuinfo_x86 *c)
 {
        u64 value;
@@ -818,6 +876,13 @@ static void init_amd_bd(struct cpuinfo_x86 *c)
                        wrmsrl_safe(MSR_F15H_IC_CFG, value);
                }
        }
+
+       /*
+        * Some BIOS implementations do not restore proper RDRAND support
+        * across suspend and resume. Check on whether to hide the RDRAND
+        * instruction support via CPUID.
+        */
+       clear_rdrand_cpuid_bit(c);
 }
 
 static void init_amd_zn(struct cpuinfo_x86 *c)
@@ -860,6 +925,7 @@ static void init_amd(struct cpuinfo_x86 *c)
        case 0x10: init_amd_gh(c); break;
        case 0x12: init_amd_ln(c); break;
        case 0x15: init_amd_bd(c); break;
+       case 0x16: init_amd_jg(c); break;
        case 0x17: init_amd_zn(c); break;
        }
 
index 685d17c1146106a5ebf8333c02bd5f029a47d071..e904ff06a83d84c9ab5ccd08bdfcc14b1cc3768a 100644 (file)
@@ -216,6 +216,9 @@ static void recalculate_apic_map(struct kvm *kvm)
                if (!apic_x2apic_mode(apic) && !new->phys_map[xapic_id])
                        new->phys_map[xapic_id] = apic;
 
+               if (!kvm_apic_sw_enabled(apic))
+                       continue;
+
                ldr = kvm_lapic_get_reg(apic, APIC_LDR);
 
                if (apic_x2apic_mode(apic)) {
@@ -258,6 +261,8 @@ static inline void apic_set_spiv(struct kvm_lapic *apic, u32 val)
                        static_key_slow_dec_deferred(&apic_sw_disabled);
                else
                        static_key_slow_inc(&apic_sw_disabled.key);
+
+               recalculate_apic_map(apic->vcpu->kvm);
        }
 }
 
index 24843cf49579936c813ee7d34fc99d3b4608344f..218b277bfda3fdd2b1dd6a7569fc360855f3cc53 100644 (file)
@@ -5653,38 +5653,7 @@ static void kvm_mmu_invalidate_zap_pages_in_memslot(struct kvm *kvm,
                        struct kvm_memory_slot *slot,
                        struct kvm_page_track_notifier_node *node)
 {
-       struct kvm_mmu_page *sp;
-       LIST_HEAD(invalid_list);
-       unsigned long i;
-       bool flush;
-       gfn_t gfn;
-
-       spin_lock(&kvm->mmu_lock);
-
-       if (list_empty(&kvm->arch.active_mmu_pages))
-               goto out_unlock;
-
-       flush = slot_handle_all_level(kvm, slot, kvm_zap_rmapp, false);
-
-       for (i = 0; i < slot->npages; i++) {
-               gfn = slot->base_gfn + i;
-
-               for_each_valid_sp(kvm, sp, gfn) {
-                       if (sp->gfn != gfn)
-                               continue;
-
-                       kvm_mmu_prepare_zap_page(kvm, sp, &invalid_list);
-               }
-               if (need_resched() || spin_needbreak(&kvm->mmu_lock)) {
-                       kvm_mmu_remote_flush_or_zap(kvm, &invalid_list, flush);
-                       flush = false;
-                       cond_resched_lock(&kvm->mmu_lock);
-               }
-       }
-       kvm_mmu_remote_flush_or_zap(kvm, &invalid_list, flush);
-
-out_unlock:
-       spin_unlock(&kvm->mmu_lock);
+       kvm_mmu_zap_all(kvm);
 }
 
 void kvm_mmu_init_vm(struct kvm *kvm)
index d685491fce4d1091f0b0bf0382cfa5d0fe77796e..e3d3b2128f2b66c031fd6a9cbb47c9b4f379b87d 100644 (file)
@@ -1714,7 +1714,6 @@ static int avic_init_backing_page(struct kvm_vcpu *vcpu)
        if (!entry)
                return -EINVAL;
 
-       new_entry = READ_ONCE(*entry);
        new_entry = __sme_set((page_to_phys(svm->avic_backing_page) &
                              AVIC_PHYSICAL_ID_ENTRY_BACKING_PAGE_MASK) |
                              AVIC_PHYSICAL_ID_ENTRY_VALID_MASK);
index eaaed5bfc4a4429a92e980252c2f993047eb90bb..991549a1c5f3ae193aedd8ae9abae4148aed0a5f 100644 (file)
@@ -390,8 +390,9 @@ static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image,
 
        emit_prologue(&prog, bpf_prog->aux->stack_depth,
                      bpf_prog_was_classic(bpf_prog));
+       addrs[0] = prog - temp;
 
-       for (i = 0; i < insn_cnt; i++, insn++) {
+       for (i = 1; i <= insn_cnt; i++, insn++) {
                const s32 imm32 = insn->imm;
                u32 dst_reg = insn->dst_reg;
                u32 src_reg = insn->src_reg;
@@ -1105,7 +1106,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
                extra_pass = true;
                goto skip_init_addrs;
        }
-       addrs = kmalloc_array(prog->len, sizeof(*addrs), GFP_KERNEL);
+       addrs = kmalloc_array(prog->len + 1, sizeof(*addrs), GFP_KERNEL);
        if (!addrs) {
                prog = orig_prog;
                goto out_addrs;
@@ -1115,7 +1116,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
         * Before first pass, make a rough estimation of addrs[]
         * each BPF instruction is translated to less than 64 bytes
         */
-       for (proglen = 0, i = 0; i < prog->len; i++) {
+       for (proglen = 0, i = 0; i <= prog->len; i++) {
                proglen += 64;
                addrs[i] = proglen;
        }
@@ -1180,7 +1181,7 @@ out_image:
 
        if (!image || !prog->is_func || extra_pass) {
                if (image)
-                       bpf_prog_fill_jited_linfo(prog, addrs);
+                       bpf_prog_fill_jited_linfo(prog, addrs + 1);
 out_addrs:
                kfree(addrs);
                kfree(jit_data);
index 24b079e94bc261b6b7b27c4aadf0ff7ec5f7ccda..c9ef6a7a4a1aa4783e515d9378fa2886451bbb02 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/smp.h>
 #include <linux/perf_event.h>
 #include <linux/tboot.h>
+#include <linux/dmi.h>
 
 #include <asm/pgtable.h>
 #include <asm/proto.h>
@@ -23,7 +24,7 @@
 #include <asm/debugreg.h>
 #include <asm/cpu.h>
 #include <asm/mmu_context.h>
-#include <linux/dmi.h>
+#include <asm/cpu_device_id.h>
 
 #ifdef CONFIG_X86_32
 __visible unsigned long saved_context_ebx;
@@ -397,15 +398,14 @@ static int __init bsp_pm_check_init(void)
 
 core_initcall(bsp_pm_check_init);
 
-static int msr_init_context(const u32 *msr_id, const int total_num)
+static int msr_build_context(const u32 *msr_id, const int num)
 {
-       int i = 0;
+       struct saved_msrs *saved_msrs = &saved_context.saved_msrs;
        struct saved_msr *msr_array;
+       int total_num;
+       int i, j;
 
-       if (saved_context.saved_msrs.array || saved_context.saved_msrs.num > 0) {
-               pr_err("x86/pm: MSR quirk already applied, please check your DMI match table.\n");
-               return -EINVAL;
-       }
+       total_num = saved_msrs->num + num;
 
        msr_array = kmalloc_array(total_num, sizeof(struct saved_msr), GFP_KERNEL);
        if (!msr_array) {
@@ -413,19 +413,30 @@ static int msr_init_context(const u32 *msr_id, const int total_num)
                return -ENOMEM;
        }
 
-       for (i = 0; i < total_num; i++) {
-               msr_array[i].info.msr_no        = msr_id[i];
+       if (saved_msrs->array) {
+               /*
+                * Multiple callbacks can invoke this function, so copy any
+                * MSR save requests from previous invocations.
+                */
+               memcpy(msr_array, saved_msrs->array,
+                      sizeof(struct saved_msr) * saved_msrs->num);
+
+               kfree(saved_msrs->array);
+       }
+
+       for (i = saved_msrs->num, j = 0; i < total_num; i++, j++) {
+               msr_array[i].info.msr_no        = msr_id[j];
                msr_array[i].valid              = false;
                msr_array[i].info.reg.q         = 0;
        }
-       saved_context.saved_msrs.num    = total_num;
-       saved_context.saved_msrs.array  = msr_array;
+       saved_msrs->num   = total_num;
+       saved_msrs->array = msr_array;
 
        return 0;
 }
 
 /*
- * The following section is a quirk framework for problematic BIOSen:
+ * The following sections are a quirk framework for problematic BIOSen:
  * Sometimes MSRs are modified by the BIOSen after suspended to
  * RAM, this might cause unexpected behavior after wakeup.
  * Thus we save/restore these specified MSRs across suspend/resume
@@ -440,7 +451,7 @@ static int msr_initialize_bdw(const struct dmi_system_id *d)
        u32 bdw_msr_id[] = { MSR_IA32_THERM_CONTROL };
 
        pr_info("x86/pm: %s detected, MSR saving is needed during suspending.\n", d->ident);
-       return msr_init_context(bdw_msr_id, ARRAY_SIZE(bdw_msr_id));
+       return msr_build_context(bdw_msr_id, ARRAY_SIZE(bdw_msr_id));
 }
 
 static const struct dmi_system_id msr_save_dmi_table[] = {
@@ -455,9 +466,58 @@ static const struct dmi_system_id msr_save_dmi_table[] = {
        {}
 };
 
+static int msr_save_cpuid_features(const struct x86_cpu_id *c)
+{
+       u32 cpuid_msr_id[] = {
+               MSR_AMD64_CPUID_FN_1,
+       };
+
+       pr_info("x86/pm: family %#hx cpu detected, MSR saving is needed during suspending.\n",
+               c->family);
+
+       return msr_build_context(cpuid_msr_id, ARRAY_SIZE(cpuid_msr_id));
+}
+
+static const struct x86_cpu_id msr_save_cpu_table[] = {
+       {
+               .vendor = X86_VENDOR_AMD,
+               .family = 0x15,
+               .model = X86_MODEL_ANY,
+               .feature = X86_FEATURE_ANY,
+               .driver_data = (kernel_ulong_t)msr_save_cpuid_features,
+       },
+       {
+               .vendor = X86_VENDOR_AMD,
+               .family = 0x16,
+               .model = X86_MODEL_ANY,
+               .feature = X86_FEATURE_ANY,
+               .driver_data = (kernel_ulong_t)msr_save_cpuid_features,
+       },
+       {}
+};
+
+typedef int (*pm_cpu_match_t)(const struct x86_cpu_id *);
+static int pm_cpu_check(const struct x86_cpu_id *c)
+{
+       const struct x86_cpu_id *m;
+       int ret = 0;
+
+       m = x86_match_cpu(msr_save_cpu_table);
+       if (m) {
+               pm_cpu_match_t fn;
+
+               fn = (pm_cpu_match_t)m->driver_data;
+               ret = fn(m);
+       }
+
+       return ret;
+}
+
 static int pm_check_save_msr(void)
 {
        dmi_check_system(msr_save_dmi_table);
+       pm_cpu_check(msr_save_cpu_table);
+
        return 0;
 }
 
index d696f165a50e6e815deef12dcc0b19d31fd22494..60bbc5090abec0a626d88dda38c3729b41cc2446 100644 (file)
@@ -219,12 +219,13 @@ static void bsw_pwm_setup(struct lpss_private_data *pdata)
 }
 
 static const struct lpss_device_desc lpt_dev_desc = {
-       .flags = LPSS_CLK | LPSS_CLK_GATE | LPSS_CLK_DIVIDER | LPSS_LTR,
+       .flags = LPSS_CLK | LPSS_CLK_GATE | LPSS_CLK_DIVIDER | LPSS_LTR
+                       | LPSS_SAVE_CTX,
        .prv_offset = 0x800,
 };
 
 static const struct lpss_device_desc lpt_i2c_dev_desc = {
-       .flags = LPSS_CLK | LPSS_CLK_GATE | LPSS_LTR,
+       .flags = LPSS_CLK | LPSS_CLK_GATE | LPSS_LTR | LPSS_SAVE_CTX,
        .prv_offset = 0x800,
 };
 
@@ -236,7 +237,8 @@ static struct property_entry uart_properties[] = {
 };
 
 static const struct lpss_device_desc lpt_uart_dev_desc = {
-       .flags = LPSS_CLK | LPSS_CLK_GATE | LPSS_CLK_DIVIDER | LPSS_LTR,
+       .flags = LPSS_CLK | LPSS_CLK_GATE | LPSS_CLK_DIVIDER | LPSS_LTR
+                       | LPSS_SAVE_CTX,
        .clk_con_id = "baudclk",
        .prv_offset = 0x800,
        .setup = lpss_uart_setup,
index 24f065114d4240160301a22999a91dc37dca046f..2c4dda0787e849af8034710760393e2b0684e5cd 100644 (file)
@@ -279,9 +279,13 @@ static int acpi_processor_get_info(struct acpi_device *device)
        }
 
        if (acpi_duplicate_processor_id(pr->acpi_id)) {
-               dev_err(&device->dev,
-                       "Failed to get unique processor _UID (0x%x)\n",
-                       pr->acpi_id);
+               if (pr->acpi_id == 0xff)
+                       dev_info_once(&device->dev,
+                               "Entry not well-defined, consider updating BIOS\n");
+               else
+                       dev_err(&device->dev,
+                               "Failed to get unique processor _UID (0x%x)\n",
+                               pr->acpi_id);
                return -ENODEV;
        }
 
index 13d513b81589207a4c9909e9577438310f4c5040..1ea52576f0a2e490c58cba27108b3eae5f9a8679 100644 (file)
@@ -134,12 +134,12 @@ struct acpi_namespace_node {
        union acpi_operand_object *object;      /* Interpreter object */
        u8 descriptor_type;     /* Differentiate object descriptor types */
        u8 type;                /* ACPI Type associated with this name */
-       u8 flags;               /* Miscellaneous flags */
-       acpi_owner_id owner_id; /* Node creator */
+       u16 flags;              /* Miscellaneous flags */
        union acpi_name_union name;     /* ACPI Name, always 4 chars per ACPI spec */
        struct acpi_namespace_node *parent;     /* Parent node */
        struct acpi_namespace_node *child;      /* First child */
        struct acpi_namespace_node *peer;       /* First peer */
+       acpi_owner_id owner_id; /* Node creator */
 
        /*
         * The following fields are used by the ASL compiler and disassembler only
index b2ef703d7df8b63361b7a00c8e2ddbd497aeadca..8def0e3d690fdaa69bb58fc78c59229df0412e52 100644 (file)
@@ -153,8 +153,8 @@ struct acpi_object_method {
        } dispatch;
 
        u32 aml_length;
-       u8 thread_count;
        acpi_owner_id owner_id;
+       u8 thread_count;
 };
 
 /* Flags for info_flags field above */
index 8a4e6b4aaf2c3761ee92adac825c1b0248781fcf..218ff4c8b81715a28da6693de901d8144e40e9d4 100644 (file)
@@ -167,9 +167,9 @@ struct acpi_evaluate_info {
        u32 return_flags;       /* Used for return value analysis */
        u32 return_btype;       /* Bitmapped type of the returned object */
        u16 param_count;        /* Count of the input argument list */
+       u16 node_flags;         /* Same as Node->Flags */
        u8 pass_number;         /* Parser pass number */
        u8 return_object_type;  /* Object type of the returned object */
-       u8 node_flags;          /* Same as Node->Flags */
        u8 flags;               /* General flags */
 };
 
index 9022537567e9d2cd184d36ae01003c8608d203cc..601808be86d18e7a73ad4d731dd0eae164aefc8a 100644 (file)
@@ -686,22 +686,26 @@ void acpi_ut_delete_address_lists(void);
 /*
  * utxferror - various error/warning output functions
  */
+ACPI_PRINTF_LIKE(5)
 void ACPI_INTERNAL_VAR_XFACE
 acpi_ut_predefined_warning(const char *module_name,
                           u32 line_number,
                           char *pathname,
-                          u8 node_flags, const char *format, ...);
+                          u16 node_flags, const char *format, ...);
 
+ACPI_PRINTF_LIKE(5)
 void ACPI_INTERNAL_VAR_XFACE
 acpi_ut_predefined_info(const char *module_name,
                        u32 line_number,
-                       char *pathname, u8 node_flags, const char *format, ...);
+                       char *pathname,
+                       u16 node_flags, const char *format, ...);
 
+ACPI_PRINTF_LIKE(5)
 void ACPI_INTERNAL_VAR_XFACE
 acpi_ut_predefined_bios_error(const char *module_name,
                              u32 line_number,
                              char *pathname,
-                             u8 node_flags, const char *format, ...);
+                             u16 node_flags, const char *format, ...);
 
 void
 acpi_ut_prefixed_namespace_error(const char *module_name,
index 7809bd94a18ddc075e406334afe5ce6ab50d49c5..47d2e50598491964561c302b455c99b19481f8cb 100644 (file)
@@ -121,7 +121,7 @@ void acpi_db_display_history(void)
 
        for (i = 0; i < acpi_gbl_num_history; i++) {
                if (acpi_gbl_history_buffer[history_index].command) {
-                       acpi_os_printf("%3ld %s\n",
+                       acpi_os_printf("%3u %s\n",
                                       acpi_gbl_history_buffer[history_index].
                                       cmd_num,
                                       acpi_gbl_history_buffer[history_index].
index 3e5f95390f0dd8a179c7e23751cf30a1d960e958..55a7e10998d87ed44f5716ab0fdc2d1b6538afe0 100644 (file)
@@ -593,7 +593,7 @@ static u32 acpi_db_get_line(char *input_buffer)
             input_buffer)) {
                acpi_os_printf
                    ("Buffer overflow while parsing input line (max %u characters)\n",
-                    sizeof(acpi_gbl_db_parsed_buf));
+                    (u32)sizeof(acpi_gbl_db_parsed_buf));
                return (0);
        }
 
@@ -853,24 +853,24 @@ acpi_db_command_dispatch(char *input_buffer,
 
                if (param_count == 0) {
                        acpi_os_printf
-                           ("Current debug level for file output is:    %8.8lX\n",
+                           ("Current debug level for file output is:    %8.8X\n",
                             acpi_gbl_db_debug_level);
                        acpi_os_printf
-                           ("Current debug level for console output is: %8.8lX\n",
+                           ("Current debug level for console output is: %8.8X\n",
                             acpi_gbl_db_console_debug_level);
                } else if (param_count == 2) {
                        temp = acpi_gbl_db_console_debug_level;
                        acpi_gbl_db_console_debug_level =
                            strtoul(acpi_gbl_db_args[1], NULL, 16);
                        acpi_os_printf
-                           ("Debug Level for console output was %8.8lX, now %8.8lX\n",
+                           ("Debug Level for console output was %8.8X, now %8.8X\n",
                             temp, acpi_gbl_db_console_debug_level);
                } else {
                        temp = acpi_gbl_db_debug_level;
                        acpi_gbl_db_debug_level =
                            strtoul(acpi_gbl_db_args[1], NULL, 16);
                        acpi_os_printf
-                           ("Debug Level for file output was %8.8lX, now %8.8lX\n",
+                           ("Debug Level for file output was %8.8X, now %8.8X\n",
                             temp, acpi_gbl_db_debug_level);
                }
                break;
index d8b7a0fe92ecd07bca1547ac26f58ea2a5e5e28e..76a15b6ffc5d3688ae5ee2b6a63b0e58178867e6 100644 (file)
@@ -302,6 +302,10 @@ acpi_status acpi_db_disassemble_method(char *name)
        }
 
        status = acpi_ut_allocate_owner_id(&obj_desc->method.owner_id);
+       if (ACPI_FAILURE(status)) {
+               return (status);
+       }
+
        walk_state->owner_id = obj_desc->method.owner_id;
 
        /* Push start scope on scope stack and make it current */
index d220168dca01a4fadf7df7380ccedc6a9a8cd41f..f9fc84bc3e84f8d0f078e58140b33541922a19fa 100644 (file)
@@ -394,7 +394,6 @@ void acpi_db_decode_locals(struct acpi_walk_state *walk_state)
        u8 display_locals = FALSE;
 
        node = walk_state->method_node;
-       obj_desc = walk_state->method_desc;
 
        /* There are no locals for the module-level code case */
 
index bf620937c79b9c28f4ab5e43b2c13ed033256e88..3af88e70238c5c4fb5a505167ee718443e2ed4ed 100644 (file)
@@ -341,17 +341,17 @@ acpi_status acpi_db_display_statistics(char *type_arg)
                               "ACPI_TYPE", "NODES", "OBJECTS");
 
                for (i = 0; i < ACPI_TYPE_NS_NODE_MAX; i++) {
-                       acpi_os_printf("%16.16s % 10ld% 10ld\n",
+                       acpi_os_printf("%16.16s %10u %10u\n",
                                       acpi_ut_get_type_name(i),
                                       acpi_gbl_node_type_count[i],
                                       acpi_gbl_obj_type_count[i]);
                }
 
-               acpi_os_printf("%16.16s % 10ld% 10ld\n", "Misc/Unknown",
+               acpi_os_printf("%16.16s %10u %10u\n", "Misc/Unknown",
                               acpi_gbl_node_type_count_misc,
                               acpi_gbl_obj_type_count_misc);
 
-               acpi_os_printf("%16.16s % 10ld% 10ld\n", "TOTALS:",
+               acpi_os_printf("%16.16s %10u %10u\n", "TOTALS:",
                               acpi_gbl_num_nodes, acpi_gbl_num_objects);
                break;
 
@@ -379,16 +379,14 @@ acpi_status acpi_db_display_statistics(char *type_arg)
        case CMD_STAT_MISC:
 
                acpi_os_printf("\nMiscellaneous Statistics:\n\n");
-               acpi_os_printf("Calls to AcpiPsFind:.. ........% 7ld\n",
+               acpi_os_printf("%-28s:     %7u\n", "Calls to AcpiPsFind",
                               acpi_gbl_ps_find_count);
-               acpi_os_printf("Calls to AcpiNsLookup:..........% 7ld\n",
+               acpi_os_printf("%-28s:     %7u\n", "Calls to AcpiNsLookup",
                               acpi_gbl_ns_lookup_count);
 
-               acpi_os_printf("\n");
-
-               acpi_os_printf("Mutex usage:\n\n");
+               acpi_os_printf("\nMutex usage:\n\n");
                for (i = 0; i < ACPI_NUM_MUTEX; i++) {
-                       acpi_os_printf("%-28s:     % 7ld\n",
+                       acpi_os_printf("%-28s:     %7u\n",
                                       acpi_ut_get_mutex_name(i),
                                       acpi_gbl_mutex_info[i].use_count);
                }
@@ -399,87 +397,87 @@ acpi_status acpi_db_display_statistics(char *type_arg)
                acpi_os_printf("\nInternal object sizes:\n\n");
 
                acpi_os_printf("Common         %3d\n",
-                              sizeof(struct acpi_object_common));
+                              (u32)sizeof(struct acpi_object_common));
                acpi_os_printf("Number         %3d\n",
-                              sizeof(struct acpi_object_integer));
+                              (u32)sizeof(struct acpi_object_integer));
                acpi_os_printf("String         %3d\n",
-                              sizeof(struct acpi_object_string));
+                              (u32)sizeof(struct acpi_object_string));
                acpi_os_printf("Buffer         %3d\n",
-                              sizeof(struct acpi_object_buffer));
+                              (u32)sizeof(struct acpi_object_buffer));
                acpi_os_printf("Package        %3d\n",
-                              sizeof(struct acpi_object_package));
+                              (u32)sizeof(struct acpi_object_package));
                acpi_os_printf("BufferField    %3d\n",
-                              sizeof(struct acpi_object_buffer_field));
+                              (u32)sizeof(struct acpi_object_buffer_field));
                acpi_os_printf("Device         %3d\n",
-                              sizeof(struct acpi_object_device));
+                              (u32)sizeof(struct acpi_object_device));
                acpi_os_printf("Event          %3d\n",
-                              sizeof(struct acpi_object_event));
+                              (u32)sizeof(struct acpi_object_event));
                acpi_os_printf("Method         %3d\n",
-                              sizeof(struct acpi_object_method));
+                              (u32)sizeof(struct acpi_object_method));
                acpi_os_printf("Mutex          %3d\n",
-                              sizeof(struct acpi_object_mutex));
+                              (u32)sizeof(struct acpi_object_mutex));
                acpi_os_printf("Region         %3d\n",
-                              sizeof(struct acpi_object_region));
+                              (u32)sizeof(struct acpi_object_region));
                acpi_os_printf("PowerResource  %3d\n",
-                              sizeof(struct acpi_object_power_resource));
+                              (u32)sizeof(struct acpi_object_power_resource));
                acpi_os_printf("Processor      %3d\n",
-                              sizeof(struct acpi_object_processor));
+                              (u32)sizeof(struct acpi_object_processor));
                acpi_os_printf("ThermalZone    %3d\n",
-                              sizeof(struct acpi_object_thermal_zone));
+                              (u32)sizeof(struct acpi_object_thermal_zone));
                acpi_os_printf("RegionField    %3d\n",
-                              sizeof(struct acpi_object_region_field));
+                              (u32)sizeof(struct acpi_object_region_field));
                acpi_os_printf("BankField      %3d\n",
-                              sizeof(struct acpi_object_bank_field));
+                              (u32)sizeof(struct acpi_object_bank_field));
                acpi_os_printf("IndexField     %3d\n",
-                              sizeof(struct acpi_object_index_field));
+                              (u32)sizeof(struct acpi_object_index_field));
                acpi_os_printf("Reference      %3d\n",
-                              sizeof(struct acpi_object_reference));
+                              (u32)sizeof(struct acpi_object_reference));
                acpi_os_printf("Notify         %3d\n",
-                              sizeof(struct acpi_object_notify_handler));
+                              (u32)sizeof(struct acpi_object_notify_handler));
                acpi_os_printf("AddressSpace   %3d\n",
-                              sizeof(struct acpi_object_addr_handler));
+                              (u32)sizeof(struct acpi_object_addr_handler));
                acpi_os_printf("Extra          %3d\n",
-                              sizeof(struct acpi_object_extra));
+                              (u32)sizeof(struct acpi_object_extra));
                acpi_os_printf("Data           %3d\n",
-                              sizeof(struct acpi_object_data));
+                              (u32)sizeof(struct acpi_object_data));
 
                acpi_os_printf("\n");
 
                acpi_os_printf("ParseObject    %3d\n",
-                              sizeof(struct acpi_parse_obj_common));
+                              (u32)sizeof(struct acpi_parse_obj_common));
                acpi_os_printf("ParseObjectNamed %3d\n",
-                              sizeof(struct acpi_parse_obj_named));
+                              (u32)sizeof(struct acpi_parse_obj_named));
                acpi_os_printf("ParseObjectAsl %3d\n",
-                              sizeof(struct acpi_parse_obj_asl));
+                              (u32)sizeof(struct acpi_parse_obj_asl));
                acpi_os_printf("OperandObject  %3d\n",
-                              sizeof(union acpi_operand_object));
+                              (u32)sizeof(union acpi_operand_object));
                acpi_os_printf("NamespaceNode  %3d\n",
-                              sizeof(struct acpi_namespace_node));
+                              (u32)sizeof(struct acpi_namespace_node));
                acpi_os_printf("AcpiObject     %3d\n",
-                              sizeof(union acpi_object));
+                              (u32)sizeof(union acpi_object));
 
                acpi_os_printf("\n");
 
                acpi_os_printf("Generic State  %3d\n",
-                              sizeof(union acpi_generic_state));
+                              (u32)sizeof(union acpi_generic_state));
                acpi_os_printf("Common State   %3d\n",
-                              sizeof(struct acpi_common_state));
+                              (u32)sizeof(struct acpi_common_state));
                acpi_os_printf("Control State  %3d\n",
-                              sizeof(struct acpi_control_state));
+                              (u32)sizeof(struct acpi_control_state));
                acpi_os_printf("Update State   %3d\n",
-                              sizeof(struct acpi_update_state));
+                              (u32)sizeof(struct acpi_update_state));
                acpi_os_printf("Scope State    %3d\n",
-                              sizeof(struct acpi_scope_state));
+                              (u32)sizeof(struct acpi_scope_state));
                acpi_os_printf("Parse Scope    %3d\n",
-                              sizeof(struct acpi_pscope_state));
+                              (u32)sizeof(struct acpi_pscope_state));
                acpi_os_printf("Package State  %3d\n",
-                              sizeof(struct acpi_pkg_state));
+                              (u32)sizeof(struct acpi_pkg_state));
                acpi_os_printf("Thread State   %3d\n",
-                              sizeof(struct acpi_thread_state));
+                              (u32)sizeof(struct acpi_thread_state));
                acpi_os_printf("Result Values  %3d\n",
-                              sizeof(struct acpi_result_values));
+                              (u32)sizeof(struct acpi_result_values));
                acpi_os_printf("Notify Info    %3d\n",
-                              sizeof(struct acpi_notify_info));
+                              (u32)sizeof(struct acpi_notify_info));
                break;
 
        case CMD_STAT_STACK:
index 6526b2deeaada44251d6869f07ae45791650fc6e..a9bc938a3b55743803241e8d0fe15c26ed177e95 100644 (file)
@@ -94,7 +94,7 @@ static struct acpi_exdump_info acpi_ex_dump_method[9] = {
         "Parameter Count"},
        {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(method.sync_level), "Sync Level"},
        {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(method.mutex), "Mutex"},
-       {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(method.owner_id), "Owner Id"},
+       {ACPI_EXD_UINT16, ACPI_EXD_OFFSET(method.owner_id), "Owner Id"},
        {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(method.thread_count), "Thread Count"},
        {ACPI_EXD_UINT32, ACPI_EXD_OFFSET(method.aml_length), "Aml Length"},
        {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(method.aml_start), "Aml Start"}
@@ -269,8 +269,8 @@ static struct acpi_exdump_info acpi_ex_dump_field_common[7] = {
 
 static struct acpi_exdump_info acpi_ex_dump_node[7] = {
        {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_node), NULL},
-       {ACPI_EXD_UINT8, ACPI_EXD_NSOFFSET(flags), "Flags"},
-       {ACPI_EXD_UINT8, ACPI_EXD_NSOFFSET(owner_id), "Owner Id"},
+       {ACPI_EXD_UINT16, ACPI_EXD_NSOFFSET(flags), "Flags"},
+       {ACPI_EXD_UINT16, ACPI_EXD_NSOFFSET(owner_id), "Owner Id"},
        {ACPI_EXD_LIST, ACPI_EXD_NSOFFSET(object), "Object List"},
        {ACPI_EXD_NODE, ACPI_EXD_NSOFFSET(parent), "Parent"},
        {ACPI_EXD_NODE, ACPI_EXD_NSOFFSET(child), "Child"},
index 2566e2d4c78031b4194ada252878b0b88194d1e4..3f045b5953b2e85ac7c2345fc568f57418c234b2 100644 (file)
@@ -598,7 +598,7 @@ acpi_ns_lookup(union acpi_generic_state *scope_info,
                                if (flags & ACPI_NS_PREFIX_MUST_EXIST) {
                                        acpi_os_printf(ACPI_MSG_BIOS_ERROR
                                                       "Object does not exist: %4.4s\n",
-                                                      &simple_name);
+                                                      (char *)&simple_name);
                                }
 #endif
                                /* Name not found in ACPI namespace */
index 6eb63db72249b0291be099310163841f2b59340e..fe9b3639a87dcbf10bc7b622417ff464d64108e6 100644 (file)
@@ -241,7 +241,7 @@ void acpi_ns_install_node(struct acpi_walk_state *walk_state, struct acpi_namesp
        node->type = (u8) type;
 
        ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
-                         "%4.4s (%s) [Node %p Owner %X] added to %4.4s (%s) [Node %p]\n",
+                         "%4.4s (%s) [Node %p Owner %3.3X] added to %4.4s (%s) [Node %p]\n",
                          acpi_ut_get_node_name(node),
                          acpi_ut_get_type_name(node->type), node, owner_id,
                          acpi_ut_get_node_name(parent_node),
index 1b12c172e115150e267d312413b4b7bdc6ce8ebe..9731d7cf1b83c1face62588ffce214a1a32986bc 100644 (file)
@@ -197,7 +197,7 @@ acpi_ns_dump_one_object(acpi_handle obj_handle,
 
        /* Now we can print out the pertinent information */
 
-       acpi_os_printf(" %-12s %p %2.2X ",
+       acpi_os_printf(" %-12s %p %3.3X ",
                       acpi_ut_get_type_name(type), this_node,
                       this_node->owner_id);
 
index 8d776256b21318827de8de97eb365ad1dc35df3d..663d85e0adba92fd2cd6f77f7608a9c01dca6bd6 100644 (file)
@@ -126,7 +126,7 @@ static const struct acpi_repair_info acpi_ns_repairable_names[] = {
 
 #define ACPI_FDE_FIELD_COUNT        5
 #define ACPI_FDE_BYTE_BUFFER_SIZE   5
-#define ACPI_FDE_DWORD_BUFFER_SIZE  (ACPI_FDE_FIELD_COUNT * sizeof (u32))
+#define ACPI_FDE_DWORD_BUFFER_SIZE  (ACPI_FDE_FIELD_COUNT * (u32) sizeof (u32))
 
 /******************************************************************************
  *
index 91a4b984f224c71ced026462db951b08c2e478f1..309440010ab2adc8dab4e27856aee74ef39f6e84 100644 (file)
@@ -750,6 +750,7 @@ acpi_status acpi_tb_delete_namespace_by_owner(u32 table_index)
        if (ACPI_FAILURE(status)) {
                return_ACPI_STATUS(status);
        }
+
        acpi_ns_delete_namespace_by_owner(owner_id);
        acpi_ut_release_write_lock(&acpi_gbl_namespace_rw_lock);
        return_ACPI_STATUS(status);
index 01b1b36c8a8e2ac5798a633b2da1cd53d283e9d3..5b169b5f0f1a3a098c2061f788bb1718364619c7 100644 (file)
@@ -158,7 +158,7 @@ acpi_debug_print(u32 requested_debug_level,
         * Display the module name, current line number, thread ID (if requested),
         * current procedure nesting level, and the current procedure name
         */
-       acpi_os_printf("%9s-%04ld ", module_name, line_number);
+       acpi_os_printf("%9s-%04d ", module_name, line_number);
 
 #ifdef ACPI_APPLICATION
        /*
@@ -177,7 +177,7 @@ acpi_debug_print(u32 requested_debug_level,
                fill_count = 0;
        }
 
-       acpi_os_printf("[%02ld] %*s",
+       acpi_os_printf("[%02d] %*s",
                       acpi_gbl_nesting_level, acpi_gbl_nesting_level + 1, " ");
        acpi_os_printf("%s%*s: ",
                       acpi_ut_trim_function_name(function_name), fill_count,
index 075457341bad19bd8c7a4b2a251533e536dda003..918aca7c4db41d62e0ba9285647b4dd9600b03ef 100644 (file)
@@ -39,7 +39,7 @@ void ACPI_INTERNAL_VAR_XFACE
 acpi_ut_predefined_warning(const char *module_name,
                           u32 line_number,
                           char *pathname,
-                          u8 node_flags, const char *format, ...)
+                          u16 node_flags, const char *format, ...)
 {
        va_list arg_list;
 
@@ -81,7 +81,7 @@ acpi_ut_predefined_warning(const char *module_name,
 void ACPI_INTERNAL_VAR_XFACE
 acpi_ut_predefined_info(const char *module_name,
                        u32 line_number,
-                       char *pathname, u8 node_flags, const char *format, ...)
+                       char *pathname, u16 node_flags, const char *format, ...)
 {
        va_list arg_list;
 
@@ -124,7 +124,7 @@ void ACPI_INTERNAL_VAR_XFACE
 acpi_ut_predefined_bios_error(const char *module_name,
                              u32 line_number,
                              char *pathname,
-                             u8 node_flags, const char *format, ...)
+                             u16 node_flags, const char *format, ...)
 {
        va_list arg_list;
 
index 688c61a90725a51635f6cd8998ade2c48736205e..ad2b218039d0f9eee89225e014dbe921afac601d 100644 (file)
@@ -65,13 +65,14 @@ static struct acpi_interface_info acpi_default_supported_interfaces[] = {
        {"Windows 2006 SP2", NULL, 0, ACPI_OSI_WIN_VISTA_SP2},  /* Windows Vista SP2 - Added 09/2010 */
        {"Windows 2009", NULL, 0, ACPI_OSI_WIN_7},      /* Windows 7 and Server 2008 R2 - Added 09/2009 */
        {"Windows 2012", NULL, 0, ACPI_OSI_WIN_8},      /* Windows 8 and Server 2012 - Added 08/2012 */
-       {"Windows 2013", NULL, 0, ACPI_OSI_WIN_8},      /* Windows 8.1 and Server 2012 R2 - Added 01/2014 */
+       {"Windows 2013", NULL, 0, ACPI_OSI_WIN_8_1},    /* Windows 8.1 and Server 2012 R2 - Added 01/2014 */
        {"Windows 2015", NULL, 0, ACPI_OSI_WIN_10},     /* Windows 10 - Added 03/2015 */
        {"Windows 2016", NULL, 0, ACPI_OSI_WIN_10_RS1}, /* Windows 10 version 1607 - Added 12/2017 */
        {"Windows 2017", NULL, 0, ACPI_OSI_WIN_10_RS2}, /* Windows 10 version 1703 - Added 12/2017 */
        {"Windows 2017.2", NULL, 0, ACPI_OSI_WIN_10_RS3},       /* Windows 10 version 1709 - Added 02/2018 */
        {"Windows 2018", NULL, 0, ACPI_OSI_WIN_10_RS4}, /* Windows 10 version 1803 - Added 11/2018 */
        {"Windows 2018.2", NULL, 0, ACPI_OSI_WIN_10_RS5},       /* Windows 10 version 1809 - Added 11/2018 */
+       {"Windows 2019", NULL, 0, ACPI_OSI_WIN_10_19H1},        /* Windows 10 version 1903 - Added 08/2019 */
 
        /* Feature Group Strings */
 
index 5eb8b76ce9d8db9a912d293b65c3ce3751ed72d4..d3525ef8ed28550eb05d0a45e90d3790612626b0 100644 (file)
@@ -38,7 +38,7 @@ acpi_status acpi_ut_allocate_owner_id(acpi_owner_id *owner_id)
 
        if (*owner_id) {
                ACPI_ERROR((AE_INFO,
-                           "Owner ID [0x%2.2X] already exists", *owner_id));
+                           "Owner ID [0x%3.3X] already exists", *owner_id));
                return_ACPI_STATUS(AE_ALREADY_EXISTS);
        }
 
@@ -88,14 +88,14 @@ acpi_status acpi_ut_allocate_owner_id(acpi_owner_id *owner_id)
                                /*
                                 * Construct encoded ID from the index and bit position
                                 *
-                                * Note: Last [j].k (bit 255) is never used and is marked
+                                * Note: Last [j].k (bit 4095) is never used and is marked
                                 * permanently allocated (prevents +1 overflow)
                                 */
                                *owner_id =
                                    (acpi_owner_id)((k + 1) + ACPI_MUL_32(j));
 
                                ACPI_DEBUG_PRINT((ACPI_DB_VALUES,
-                                                 "Allocated OwnerId: %2.2X\n",
+                                                 "Allocated OwnerId: 0x%3.3X\n",
                                                  (unsigned int)*owner_id));
                                goto exit;
                        }
@@ -116,7 +116,7 @@ acpi_status acpi_ut_allocate_owner_id(acpi_owner_id *owner_id)
         */
        status = AE_OWNER_ID_LIMIT;
        ACPI_ERROR((AE_INFO,
-                   "Could not allocate new OwnerId (255 max), AE_OWNER_ID_LIMIT"));
+                   "Could not allocate new OwnerId (4095 max), AE_OWNER_ID_LIMIT"));
 
 exit:
        (void)acpi_ut_release_mutex(ACPI_MTX_CACHES);
@@ -153,7 +153,7 @@ void acpi_ut_release_owner_id(acpi_owner_id *owner_id_ptr)
        /* Zero is not a valid owner_ID */
 
        if (owner_id == 0) {
-               ACPI_ERROR((AE_INFO, "Invalid OwnerId: 0x%2.2X", owner_id));
+               ACPI_ERROR((AE_INFO, "Invalid OwnerId: 0x%3.3X", owner_id));
                return_VOID;
        }
 
@@ -179,7 +179,7 @@ void acpi_ut_release_owner_id(acpi_owner_id *owner_id_ptr)
                acpi_gbl_owner_id_mask[index] ^= bit;
        } else {
                ACPI_ERROR((AE_INFO,
-                           "Release of non-allocated OwnerId: 0x%2.2X",
+                           "Attempted release of non-allocated OwnerId: 0x%3.3X",
                            owner_id + 1));
        }
 
index a66e00fe31fec16774bbb795c50427183c137e27..777f6f7122b404a3bbdbd2712e023e1fc6fb2f0a 100644 (file)
@@ -153,6 +153,7 @@ static void ghes_unmap(void __iomem *vaddr, enum fixed_addresses fixmap_idx)
 int ghes_estatus_pool_init(int num_ghes)
 {
        unsigned long addr, len;
+       int rc;
 
        ghes_estatus_pool = gen_pool_create(GHES_ESTATUS_POOL_MIN_ALLOC_ORDER, -1);
        if (!ghes_estatus_pool)
@@ -164,7 +165,7 @@ int ghes_estatus_pool_init(int num_ghes)
        ghes_estatus_pool_size_request = PAGE_ALIGN(len);
        addr = (unsigned long)vmalloc(PAGE_ALIGN(len));
        if (!addr)
-               return -ENOMEM;
+               goto err_pool_alloc;
 
        /*
         * New allocation must be visible in all pgd before it can be found by
@@ -172,7 +173,19 @@ int ghes_estatus_pool_init(int num_ghes)
         */
        vmalloc_sync_all();
 
-       return gen_pool_add(ghes_estatus_pool, addr, PAGE_ALIGN(len), -1);
+       rc = gen_pool_add(ghes_estatus_pool, addr, PAGE_ALIGN(len), -1);
+       if (rc)
+               goto err_pool_add;
+
+       return 0;
+
+err_pool_add:
+       vfree((void *)addr);
+
+err_pool_alloc:
+       gen_pool_destroy(ghes_estatus_pool);
+
+       return -ENOMEM;
 }
 
 static int map_gen_v2(struct ghes *ghes)
@@ -483,7 +496,7 @@ static void ghes_do_proc(struct ghes *ghes,
        int sev, sec_sev;
        struct acpi_hest_generic_data *gdata;
        guid_t *sec_type;
-       guid_t *fru_id = &NULL_UUID_LE;
+       const guid_t *fru_id = &guid_null;
        char *fru_text = "";
 
        sev = ghes_severity(estatus->error_severity);
index 15f103d7532b09d83ec9df1475bfba0a0dd7fe76..3b2525908dd8cfaed9074d7926d2036102e77f34 100644 (file)
@@ -365,8 +365,10 @@ static int acpi_get_psd(struct cpc_desc *cpc_ptr, acpi_handle handle)
        union acpi_object  *psd = NULL;
        struct acpi_psd_package *pdomain;
 
-       status = acpi_evaluate_object_typed(handle, "_PSD", NULL, &buffer,
-                       ACPI_TYPE_PACKAGE);
+       status = acpi_evaluate_object_typed(handle, "_PSD", NULL,
+                                           &buffer, ACPI_TYPE_PACKAGE);
+       if (status == AE_NOT_FOUND)     /* _PSD is optional */
+               return 0;
        if (ACPI_FAILURE(status))
                return -ENODEV;
 
index b2ef4c2ec955d5c737a69aac1cde444dcd351caf..fd66a736621cff9627b7c6bec47e2079f48de684 100644 (file)
@@ -49,8 +49,10 @@ static ssize_t cm_write(struct file *file, const char __user * user_buf,
        if ((*ppos > max_size) ||
            (*ppos + count > max_size) ||
            (*ppos + count < count) ||
-           (count > uncopied_bytes))
+           (count > uncopied_bytes)) {
+               kfree(buf);
                return -EINVAL;
+       }
 
        if (copy_from_user(buf + (*ppos), user_buf, count)) {
                kfree(buf);
@@ -70,6 +72,7 @@ static ssize_t cm_write(struct file *file, const char __user * user_buf,
                add_taint(TAINT_OVERRIDDEN_ACPI_TABLE, LOCKDEP_NOW_UNRELIABLE);
        }
 
+       kfree(buf);
        return count;
 }
 
index 96b7d39a97c65db544a7e8ec32159f57c595d673..8f9a28a870b0c5a4315c683abe7a67b0da28a664 100644 (file)
 #include <linux/init.h>
 #include <linux/list.h>
 #include <linux/list_sort.h>
+#include <linux/memory.h>
+#include <linux/mutex.h>
 #include <linux/node.h>
 #include <linux/sysfs.h>
 
-static __initdata u8 hmat_revision;
+static u8 hmat_revision;
 
-static __initdata LIST_HEAD(targets);
-static __initdata LIST_HEAD(initiators);
-static __initdata LIST_HEAD(localities);
+static LIST_HEAD(targets);
+static LIST_HEAD(initiators);
+static LIST_HEAD(localities);
+
+static DEFINE_MUTEX(target_lock);
 
 /*
  * The defined enum order is used to prioritize attributes to break ties when
@@ -36,11 +40,19 @@ enum locality_types {
 
 static struct memory_locality *localities_types[4];
 
+struct target_cache {
+       struct list_head node;
+       struct node_cache_attrs cache_attrs;
+};
+
 struct memory_target {
        struct list_head node;
        unsigned int memory_pxm;
        unsigned int processor_pxm;
        struct node_hmem_attrs hmem_attrs;
+       struct list_head caches;
+       struct node_cache_attrs cache_attrs;
+       bool registered;
 };
 
 struct memory_initiator {
@@ -53,7 +65,7 @@ struct memory_locality {
        struct acpi_hmat_locality *hmat_loc;
 };
 
-static __init struct memory_initiator *find_mem_initiator(unsigned int cpu_pxm)
+static struct memory_initiator *find_mem_initiator(unsigned int cpu_pxm)
 {
        struct memory_initiator *initiator;
 
@@ -63,7 +75,7 @@ static __init struct memory_initiator *find_mem_initiator(unsigned int cpu_pxm)
        return NULL;
 }
 
-static __init struct memory_target *find_mem_target(unsigned int mem_pxm)
+static struct memory_target *find_mem_target(unsigned int mem_pxm)
 {
        struct memory_target *target;
 
@@ -96,9 +108,6 @@ static __init void alloc_memory_target(unsigned int mem_pxm)
 {
        struct memory_target *target;
 
-       if (pxm_to_node(mem_pxm) == NUMA_NO_NODE)
-               return;
-
        target = find_mem_target(mem_pxm);
        if (target)
                return;
@@ -110,6 +119,7 @@ static __init void alloc_memory_target(unsigned int mem_pxm)
        target->memory_pxm = mem_pxm;
        target->processor_pxm = PXM_INVAL;
        list_add_tail(&target->node, &targets);
+       INIT_LIST_HEAD(&target->caches);
 }
 
 static __init const char *hmat_data_type(u8 type)
@@ -148,7 +158,7 @@ static __init const char *hmat_data_type_suffix(u8 type)
        }
 }
 
-static __init u32 hmat_normalize(u16 entry, u64 base, u8 type)
+static u32 hmat_normalize(u16 entry, u64 base, u8 type)
 {
        u32 value;
 
@@ -183,7 +193,7 @@ static __init u32 hmat_normalize(u16 entry, u64 base, u8 type)
        return value;
 }
 
-static __init void hmat_update_target_access(struct memory_target *target,
+static void hmat_update_target_access(struct memory_target *target,
                                             u8 type, u32 value)
 {
        switch (type) {
@@ -314,7 +324,8 @@ static __init int hmat_parse_cache(union acpi_subtable_headers *header,
                                   const unsigned long end)
 {
        struct acpi_hmat_cache *cache = (void *)header;
-       struct node_cache_attrs cache_attrs;
+       struct memory_target *target;
+       struct target_cache *tcache;
        u32 attrs;
 
        if (cache->header.length < sizeof(*cache)) {
@@ -328,37 +339,47 @@ static __init int hmat_parse_cache(union acpi_subtable_headers *header,
                cache->memory_PD, cache->cache_size, attrs,
                cache->number_of_SMBIOShandles);
 
-       cache_attrs.size = cache->cache_size;
-       cache_attrs.level = (attrs & ACPI_HMAT_CACHE_LEVEL) >> 4;
-       cache_attrs.line_size = (attrs & ACPI_HMAT_CACHE_LINE_SIZE) >> 16;
+       target = find_mem_target(cache->memory_PD);
+       if (!target)
+               return 0;
+
+       tcache = kzalloc(sizeof(*tcache), GFP_KERNEL);
+       if (!tcache) {
+               pr_notice_once("Failed to allocate HMAT cache info\n");
+               return 0;
+       }
+
+       tcache->cache_attrs.size = cache->cache_size;
+       tcache->cache_attrs.level = (attrs & ACPI_HMAT_CACHE_LEVEL) >> 4;
+       tcache->cache_attrs.line_size = (attrs & ACPI_HMAT_CACHE_LINE_SIZE) >> 16;
 
        switch ((attrs & ACPI_HMAT_CACHE_ASSOCIATIVITY) >> 8) {
        case ACPI_HMAT_CA_DIRECT_MAPPED:
-               cache_attrs.indexing = NODE_CACHE_DIRECT_MAP;
+               tcache->cache_attrs.indexing = NODE_CACHE_DIRECT_MAP;
                break;
        case ACPI_HMAT_CA_COMPLEX_CACHE_INDEXING:
-               cache_attrs.indexing = NODE_CACHE_INDEXED;
+               tcache->cache_attrs.indexing = NODE_CACHE_INDEXED;
                break;
        case ACPI_HMAT_CA_NONE:
        default:
-               cache_attrs.indexing = NODE_CACHE_OTHER;
+               tcache->cache_attrs.indexing = NODE_CACHE_OTHER;
                break;
        }
 
        switch ((attrs & ACPI_HMAT_WRITE_POLICY) >> 12) {
        case ACPI_HMAT_CP_WB:
-               cache_attrs.write_policy = NODE_CACHE_WRITE_BACK;
+               tcache->cache_attrs.write_policy = NODE_CACHE_WRITE_BACK;
                break;
        case ACPI_HMAT_CP_WT:
-               cache_attrs.write_policy = NODE_CACHE_WRITE_THROUGH;
+               tcache->cache_attrs.write_policy = NODE_CACHE_WRITE_THROUGH;
                break;
        case ACPI_HMAT_CP_NONE:
        default:
-               cache_attrs.write_policy = NODE_CACHE_WRITE_OTHER;
+               tcache->cache_attrs.write_policy = NODE_CACHE_WRITE_OTHER;
                break;
        }
+       list_add_tail(&tcache->node, &target->caches);
 
-       node_add_cache(pxm_to_node(cache->memory_PD), &cache_attrs);
        return 0;
 }
 
@@ -435,7 +456,7 @@ static __init int srat_parse_mem_affinity(union acpi_subtable_headers *header,
        return 0;
 }
 
-static __init u32 hmat_initiator_perf(struct memory_target *target,
+static u32 hmat_initiator_perf(struct memory_target *target,
                               struct memory_initiator *initiator,
                               struct acpi_hmat_locality *hmat_loc)
 {
@@ -473,7 +494,7 @@ static __init u32 hmat_initiator_perf(struct memory_target *target,
                              hmat_loc->data_type);
 }
 
-static __init bool hmat_update_best(u8 type, u32 value, u32 *best)
+static bool hmat_update_best(u8 type, u32 value, u32 *best)
 {
        bool updated = false;
 
@@ -517,7 +538,7 @@ static int initiator_cmp(void *priv, struct list_head *a, struct list_head *b)
        return ia->processor_pxm - ib->processor_pxm;
 }
 
-static __init void hmat_register_target_initiators(struct memory_target *target)
+static void hmat_register_target_initiators(struct memory_target *target)
 {
        static DECLARE_BITMAP(p_nodes, MAX_NUMNODES);
        struct memory_initiator *initiator;
@@ -577,29 +598,89 @@ static __init void hmat_register_target_initiators(struct memory_target *target)
        }
 }
 
-static __init void hmat_register_target_perf(struct memory_target *target)
+static void hmat_register_target_cache(struct memory_target *target)
+{
+       unsigned mem_nid = pxm_to_node(target->memory_pxm);
+       struct target_cache *tcache;
+
+       list_for_each_entry(tcache, &target->caches, node)
+               node_add_cache(mem_nid, &tcache->cache_attrs);
+}
+
+static void hmat_register_target_perf(struct memory_target *target)
 {
        unsigned mem_nid = pxm_to_node(target->memory_pxm);
        node_set_perf_attrs(mem_nid, &target->hmem_attrs, 0);
 }
 
-static __init void hmat_register_targets(void)
+static void hmat_register_target(struct memory_target *target)
 {
-       struct memory_target *target;
+       int nid = pxm_to_node(target->memory_pxm);
 
-       list_for_each_entry(target, &targets, node) {
+       /*
+        * Skip offline nodes. This can happen when memory
+        * marked EFI_MEMORY_SP, "specific purpose", is applied
+        * to all the memory in a promixity domain leading to
+        * the node being marked offline / unplugged, or if
+        * memory-only "hotplug" node is offline.
+        */
+       if (nid == NUMA_NO_NODE || !node_online(nid))
+               return;
+
+       mutex_lock(&target_lock);
+       if (!target->registered) {
                hmat_register_target_initiators(target);
+               hmat_register_target_cache(target);
                hmat_register_target_perf(target);
+               target->registered = true;
        }
+       mutex_unlock(&target_lock);
+}
+
+static void hmat_register_targets(void)
+{
+       struct memory_target *target;
+
+       list_for_each_entry(target, &targets, node)
+               hmat_register_target(target);
+}
+
+static int hmat_callback(struct notifier_block *self,
+                        unsigned long action, void *arg)
+{
+       struct memory_target *target;
+       struct memory_notify *mnb = arg;
+       int pxm, nid = mnb->status_change_nid;
+
+       if (nid == NUMA_NO_NODE || action != MEM_ONLINE)
+               return NOTIFY_OK;
+
+       pxm = node_to_pxm(nid);
+       target = find_mem_target(pxm);
+       if (!target)
+               return NOTIFY_OK;
+
+       hmat_register_target(target);
+       return NOTIFY_OK;
 }
 
+static struct notifier_block hmat_callback_nb = {
+       .notifier_call = hmat_callback,
+       .priority = 2,
+};
+
 static __init void hmat_free_structures(void)
 {
        struct memory_target *target, *tnext;
        struct memory_locality *loc, *lnext;
        struct memory_initiator *initiator, *inext;
+       struct target_cache *tcache, *cnext;
 
        list_for_each_entry_safe(target, tnext, &targets, node) {
+               list_for_each_entry_safe(tcache, cnext, &target->caches, node) {
+                       list_del(&tcache->node);
+                       kfree(tcache);
+               }
                list_del(&target->node);
                kfree(target);
        }
@@ -658,6 +739,10 @@ static __init int hmat_init(void)
                }
        }
        hmat_register_targets();
+
+       /* Keep the table and structures if the notifier may use them */
+       if (!register_hotmemory_notifier(&hmat_callback_nb))
+               return 0;
 out_put:
        hmat_free_structures();
        acpi_put_table(tbl);
index d2549ae65e1b6f049c0c68199010f0d652433c70..dea8a60e18a4c00929cb6f7c759615f075bcfe12 100644 (file)
@@ -449,8 +449,10 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
                 * No IRQ known to the ACPI subsystem - maybe the BIOS /
                 * driver reported one, then use it. Exit in any case.
                 */
-               if (!acpi_pci_irq_valid(dev, pin))
+               if (!acpi_pci_irq_valid(dev, pin)) {
+                       kfree(entry);
                        return 0;
+               }
 
                if (acpi_isa_register_gsi(dev))
                        dev_warn(&dev->dev, "PCI INT %c: no GSI\n",
index db11f7771ef1b9ed401c99fb047c275bd8f7079f..00a6da2121be30bd08de4bcbe2f9a6e9a12c4488 100644 (file)
@@ -661,7 +661,7 @@ int acpi_pci_link_allocate_irq(acpi_handle handle, int index, int *triggering,
        ACPI_DEBUG_PRINT((ACPI_DB_INFO,
                          "Link %s is referenced\n",
                          acpi_device_bid(link->device)));
-       return (link->irq.active);
+       return link->irq.active;
 }
 
 /*
@@ -712,7 +712,7 @@ int acpi_pci_link_free_irq(acpi_handle handle)
                acpi_evaluate_object(link->device->handle, "_DIS", NULL, NULL);
 
        mutex_unlock(&acpi_link_lock);
-       return (link->irq.active);
+       return link->irq.active;
 }
 
 /* --------------------------------------------------------------------------
index 06372a37df10f1da6e345f73020bbae53aa68c5d..c3522bb8279246861da743b7841492ef8b578d8c 100644 (file)
@@ -15,8 +15,6 @@ enum acpi_smb_protocol {
        SMBUS_BLOCK_PROCESS_CALL = 0xd,
 };
 
-static const u8 SMBUS_PEC = 0x80;
-
 enum acpi_sbs_device_addr {
        ACPI_SBS_CHARGER = 0x9,
        ACPI_SBS_MANAGER = 0xa,
index 00f12a86ecbd42fc5ca401bef64b2a03d8249c7f..d831a61e0010eaf69dd16c96f0983315cf0a0972 100644 (file)
@@ -225,13 +225,9 @@ static int acpi_thermal_set_cooling_mode(struct acpi_thermal *tz, int mode)
        if (!tz)
                return -EINVAL;
 
-       if (!acpi_has_method(tz->device->handle, "_SCP")) {
-               ACPI_DEBUG_PRINT((ACPI_DB_INFO, "_SCP not present\n"));
+       if (ACPI_FAILURE(acpi_execute_simple_method(tz->device->handle,
+                                                   "_SCP", mode)))
                return -ENODEV;
-       } else if (ACPI_FAILURE(acpi_execute_simple_method(tz->device->handle,
-                                                          "_SCP", mode))) {
-               return -ENODEV;
-       }
 
        return 0;
 }
@@ -463,8 +459,7 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
                        break;
        }
 
-       if ((flag & ACPI_TRIPS_DEVICES)
-           && acpi_has_method(tz->device->handle, "_TZD")) {
+       if (flag & ACPI_TRIPS_DEVICES) {
                memset(&devices, 0, sizeof(devices));
                status = acpi_evaluate_reference(tz->device->handle, "_TZD",
                                                NULL, &devices);
index 9c0bb771751d8d986b7f53d1724f1077f9412a1f..a2fcde582e2a1614d21f0edf21faee4870668b5a 100644 (file)
@@ -74,7 +74,7 @@ struct ht16k33_priv {
        struct ht16k33_fbdev fbdev;
 };
 
-static struct fb_fix_screeninfo ht16k33_fb_fix = {
+static const struct fb_fix_screeninfo ht16k33_fb_fix = {
        .id             = DRIVER_NAME,
        .type           = FB_TYPE_PACKED_PIXELS,
        .visual         = FB_VISUAL_MONO10,
@@ -85,7 +85,7 @@ static struct fb_fix_screeninfo ht16k33_fb_fix = {
        .accel          = FB_ACCEL_NONE,
 };
 
-static struct fb_var_screeninfo ht16k33_fb_var = {
+static const struct fb_var_screeninfo ht16k33_fb_var = {
        .xres = HT16K33_MATRIX_LED_MAX_ROWS,
        .yres = HT16K33_MATRIX_LED_MAX_COLS,
        .xres_virtual = HT16K33_MATRIX_LED_MAX_ROWS,
index 9bd4ddd12b25c542ae9fad6fae963f66414b496c..5b248763a672414e925f217216fc21c9a2a257fb 100644 (file)
@@ -322,6 +322,8 @@ static int drbd_thread_setup(void *arg)
                 thi->name[0],
                 resource->name);
 
+       allow_kernel_signal(DRBD_SIGKILL);
+       allow_kernel_signal(SIGXCPU);
 restart:
        retval = thi->function(thi);
 
index 8b33128dccee1a0d26965b889190ca37e8d8372d..0875470a7806f8658c45b2b4a15f6e2b029bf0c2 100644 (file)
@@ -99,6 +99,27 @@ static int qca_send_reset(struct hci_dev *hdev)
        return 0;
 }
 
+int qca_send_pre_shutdown_cmd(struct hci_dev *hdev)
+{
+       struct sk_buff *skb;
+       int err;
+
+       bt_dev_dbg(hdev, "QCA pre shutdown cmd");
+
+       skb = __hci_cmd_sync(hdev, QCA_PRE_SHUTDOWN_CMD, 0,
+                               NULL, HCI_INIT_TIMEOUT);
+       if (IS_ERR(skb)) {
+               err = PTR_ERR(skb);
+               bt_dev_err(hdev, "QCA preshutdown_cmd failed (%d)", err);
+               return err;
+       }
+
+       kfree_skb(skb);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(qca_send_pre_shutdown_cmd);
+
 static void qca_tlv_check_data(struct rome_config *config,
                                const struct firmware *fw)
 {
@@ -119,6 +140,7 @@ static void qca_tlv_check_data(struct rome_config *config,
        BT_DBG("Length\t\t : %d bytes", length);
 
        config->dnld_mode = ROME_SKIP_EVT_NONE;
+       config->dnld_type = ROME_SKIP_EVT_NONE;
 
        switch (config->type) {
        case TLV_TYPE_PATCH:
@@ -268,7 +290,7 @@ static int qca_inject_cmd_complete_event(struct hci_dev *hdev)
 
        evt = skb_put(skb, sizeof(*evt));
        evt->ncmd = 1;
-       evt->opcode = QCA_HCI_CC_OPCODE;
+       evt->opcode = cpu_to_le16(QCA_HCI_CC_OPCODE);
 
        skb_put_u8(skb, QCA_HCI_CC_SUCCESS);
 
@@ -323,7 +345,7 @@ static int qca_download_firmware(struct hci_dev *hdev,
         */
        if (config->dnld_type == ROME_SKIP_EVT_VSE_CC ||
            config->dnld_type == ROME_SKIP_EVT_VSE)
-               return qca_inject_cmd_complete_event(hdev);
+               ret = qca_inject_cmd_complete_event(hdev);
 
 out:
        release_firmware(fw);
@@ -388,6 +410,9 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
                return err;
        }
 
+       /* Give the controller some time to get ready to receive the NVM */
+       msleep(10);
+
        /* Download NVM configuration */
        config.type = TLV_TYPE_NVM;
        if (firmware_name)
index 6a291a7a5d9658c1987cf8c01ad34c47e3d4bfc9..69c5315a65fd2630346591e5df2d3faf51690099 100644 (file)
@@ -13,6 +13,7 @@
 #define EDL_PATCH_TLV_REQ_CMD          (0x1E)
 #define EDL_NVM_ACCESS_SET_REQ_CMD     (0x01)
 #define MAX_SIZE_PER_TLV_SEGMENT       (243)
+#define QCA_PRE_SHUTDOWN_CMD           (0xFC08)
 
 #define EDL_CMD_REQ_RES_EVT            (0x00)
 #define EDL_PATCH_VER_RES_EVT          (0x19)
@@ -135,6 +136,7 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
                   const char *firmware_name);
 int qca_read_soc_version(struct hci_dev *hdev, u32 *soc_version);
 int qca_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr);
+int qca_send_pre_shutdown_cmd(struct hci_dev *hdev);
 static inline bool qca_is_wcn399x(enum qca_btsoc_type soc_type)
 {
        return soc_type == QCA_WCN3990 || soc_type == QCA_WCN3998;
@@ -167,4 +169,9 @@ static inline bool qca_is_wcn399x(enum qca_btsoc_type soc_type)
 {
        return false;
 }
+
+static inline int qca_send_pre_shutdown_cmd(struct hci_dev *hdev)
+{
+       return -EOPNOTSUPP;
+}
 #endif
index 3876fee6ad13fa617858d9b1da34ba5b43da13c9..5cf0734eb31bf923de8c18cb8e8ad5d23a284a2f 100644 (file)
@@ -2762,8 +2762,10 @@ static int btusb_mtk_setup_firmware(struct hci_dev *hdev, const char *fwname)
        fw_size = fw->size;
 
        /* The size of patch header is 30 bytes, should be skip */
-       if (fw_size < 30)
+       if (fw_size < 30) {
+               err = -EINVAL;
                goto err_release_fw;
+       }
 
        fw_size -= 30;
        fw_ptr += 30;
index 82a0a3691a63c701075e03ed44a408d13d7c4e66..9a970fd1975aab411d96912593606b5096d81180 100644 (file)
@@ -705,7 +705,7 @@ static void device_want_to_sleep(struct hci_uart *hu)
        unsigned long flags;
        struct qca_data *qca = hu->priv;
 
-       BT_DBG("hu %p want to sleep", hu);
+       BT_DBG("hu %p want to sleep in %d state", hu, qca->rx_ibs_state);
 
        spin_lock_irqsave(&qca->hci_ibs_lock, flags);
 
@@ -720,7 +720,7 @@ static void device_want_to_sleep(struct hci_uart *hu)
                break;
 
        case HCI_IBS_RX_ASLEEP:
-               /* Fall through */
+               break;
 
        default:
                /* Any other state is illegal */
@@ -912,7 +912,7 @@ static int qca_recv_event(struct hci_dev *hdev, struct sk_buff *skb)
                if (hdr->evt == HCI_EV_VENDOR)
                        complete(&qca->drop_ev_comp);
 
-               kfree(skb);
+               kfree_skb(skb);
 
                return 0;
        }
@@ -1386,6 +1386,9 @@ static int qca_power_off(struct hci_dev *hdev)
 {
        struct hci_uart *hu = hci_get_drvdata(hdev);
 
+       /* Perform pre shutdown command */
+       qca_send_pre_shutdown_cmd(hdev);
+
        qca_power_shutdown(hu);
        return 0;
 }
index c0990703ce5403c1092bda6d982c56dffd70e6a0..1c46babeb09330e8e2a98060ad310fabba65aa2d 100644 (file)
@@ -324,6 +324,25 @@ static struct clk_core *clk_core_lookup(const char *name)
        return NULL;
 }
 
+#ifdef CONFIG_OF
+static int of_parse_clkspec(const struct device_node *np, int index,
+                           const char *name, struct of_phandle_args *out_args);
+static struct clk_hw *
+of_clk_get_hw_from_clkspec(struct of_phandle_args *clkspec);
+#else
+static inline int of_parse_clkspec(const struct device_node *np, int index,
+                                  const char *name,
+                                  struct of_phandle_args *out_args)
+{
+       return -ENOENT;
+}
+static inline struct clk_hw *
+of_clk_get_hw_from_clkspec(struct of_phandle_args *clkspec)
+{
+       return ERR_PTR(-ENOENT);
+}
+#endif
+
 /**
  * clk_core_get - Find the clk_core parent of a clk
  * @core: clk to find parent of
@@ -355,8 +374,9 @@ static struct clk_core *clk_core_lookup(const char *name)
  *      };
  *
  * Returns: -ENOENT when the provider can't be found or the clk doesn't
- * exist in the provider. -EINVAL when the name can't be found. NULL when the
- * provider knows about the clk but it isn't provided on this system.
+ * exist in the provider or the name can't be found in the DT node or
+ * in a clkdev lookup. NULL when the provider knows about the clk but it
+ * isn't provided on this system.
  * A valid clk_core pointer when the clk can be found in the provider.
  */
 static struct clk_core *clk_core_get(struct clk_core *core, u8 p_index)
@@ -367,17 +387,19 @@ static struct clk_core *clk_core_get(struct clk_core *core, u8 p_index)
        struct device *dev = core->dev;
        const char *dev_id = dev ? dev_name(dev) : NULL;
        struct device_node *np = core->of_node;
+       struct of_phandle_args clkspec;
 
-       if (np && (name || index >= 0))
-               hw = of_clk_get_hw(np, index, name);
-
-       /*
-        * If the DT search above couldn't find the provider or the provider
-        * didn't know about this clk, fallback to looking up via clkdev based
-        * clk_lookups
-        */
-       if (PTR_ERR(hw) == -ENOENT && name)
+       if (np && (name || index >= 0) &&
+           !of_parse_clkspec(np, index, name, &clkspec)) {
+               hw = of_clk_get_hw_from_clkspec(&clkspec);
+               of_node_put(clkspec.np);
+       } else if (name) {
+               /*
+                * If the DT search above couldn't find the provider fallback to
+                * looking up via clkdev based clk_lookups.
+                */
                hw = clk_find_hw(dev_id, name);
+       }
 
        if (IS_ERR(hw))
                return ERR_CAST(hw);
@@ -401,7 +423,7 @@ static void clk_core_fill_parent_index(struct clk_core *core, u8 index)
                        parent = ERR_PTR(-EPROBE_DEFER);
        } else {
                parent = clk_core_get(core, index);
-               if (IS_ERR(parent) && PTR_ERR(parent) == -ENOENT)
+               if (IS_ERR(parent) && PTR_ERR(parent) == -ENOENT && entry->name)
                        parent = clk_core_lookup(entry->name);
        }
 
@@ -1632,7 +1654,8 @@ static int clk_fetch_parent_index(struct clk_core *core,
                        break;
 
                /* Fallback to comparing globally unique names */
-               if (!strcmp(parent->name, core->parents[i].name))
+               if (core->parents[i].name &&
+                   !strcmp(parent->name, core->parents[i].name))
                        break;
        }
 
index 91db7894125df5bcf6cc1b5c014d4307a9520c25..65c82d922b05cbb0e22bd9438627d8fde7120542 100644 (file)
@@ -14,7 +14,7 @@
 #include "clk-exynos5-subcmu.h"
 
 static struct samsung_clk_provider *ctx;
-static const struct exynos5_subcmu_info *cmu;
+static const struct exynos5_subcmu_info **cmu;
 static int nr_cmus;
 
 static void exynos5_subcmu_clk_save(void __iomem *base,
@@ -56,17 +56,17 @@ static void exynos5_subcmu_defer_gate(struct samsung_clk_provider *ctx,
  * when OF-core populates all device-tree nodes.
  */
 void exynos5_subcmus_init(struct samsung_clk_provider *_ctx, int _nr_cmus,
-                         const struct exynos5_subcmu_info *_cmu)
+                         const struct exynos5_subcmu_info **_cmu)
 {
        ctx = _ctx;
        cmu = _cmu;
        nr_cmus = _nr_cmus;
 
        for (; _nr_cmus--; _cmu++) {
-               exynos5_subcmu_defer_gate(ctx, _cmu->gate_clks,
-                                         _cmu->nr_gate_clks);
-               exynos5_subcmu_clk_save(ctx->reg_base, _cmu->suspend_regs,
-                                       _cmu->nr_suspend_regs);
+               exynos5_subcmu_defer_gate(ctx, (*_cmu)->gate_clks,
+                                         (*_cmu)->nr_gate_clks);
+               exynos5_subcmu_clk_save(ctx->reg_base, (*_cmu)->suspend_regs,
+                                       (*_cmu)->nr_suspend_regs);
        }
 }
 
@@ -163,9 +163,9 @@ static int __init exynos5_clk_probe(struct platform_device *pdev)
                if (of_property_read_string(np, "label", &name) < 0)
                        continue;
                for (i = 0; i < nr_cmus; i++)
-                       if (strcmp(cmu[i].pd_name, name) == 0)
+                       if (strcmp(cmu[i]->pd_name, name) == 0)
                                exynos5_clk_register_subcmu(&pdev->dev,
-                                                           &cmu[i], np);
+                                                           cmu[i], np);
        }
        return 0;
 }
index 755ee8aaa3de5670f41ae60b1b691436fa5f457b..9ae5356f25aa4170fa5a91834a7fa926246e71f4 100644 (file)
@@ -21,6 +21,6 @@ struct exynos5_subcmu_info {
 };
 
 void exynos5_subcmus_init(struct samsung_clk_provider *ctx, int nr_cmus,
-                         const struct exynos5_subcmu_info *cmu);
+                         const struct exynos5_subcmu_info **cmu);
 
 #endif
index f2b8968817682458d13c0eb1452179219ec242e9..931c70a4da196871cb75a7026908a30c1f5c286c 100644 (file)
@@ -681,6 +681,10 @@ static const struct exynos5_subcmu_info exynos5250_disp_subcmu = {
        .pd_name        = "DISP1",
 };
 
+static const struct exynos5_subcmu_info *exynos5250_subcmus[] = {
+       &exynos5250_disp_subcmu,
+};
+
 static const struct samsung_pll_rate_table vpll_24mhz_tbl[] __initconst = {
        /* sorted in descending order */
        /* PLL_36XX_RATE(rate, m, p, s, k) */
@@ -843,7 +847,8 @@ static void __init exynos5250_clk_init(struct device_node *np)
 
        samsung_clk_sleep_init(reg_base, exynos5250_clk_regs,
                               ARRAY_SIZE(exynos5250_clk_regs));
-       exynos5_subcmus_init(ctx, 1, &exynos5250_disp_subcmu);
+       exynos5_subcmus_init(ctx, ARRAY_SIZE(exynos5250_subcmus),
+                            exynos5250_subcmus);
 
        samsung_clk_of_add_provider(np, ctx);
 
index 01bca5a498b2a1e330287e465401aa7f330a37ae..7670cc596c74245205babf39e339c8e0b5e087f6 100644 (file)
@@ -534,8 +534,6 @@ static const struct samsung_gate_clock exynos5800_gate_clks[] __initconst = {
                                GATE_BUS_TOP, 24, 0, 0),
        GATE(CLK_ACLK432_SCALER, "aclk432_scaler", "mout_user_aclk432_scaler",
                                GATE_BUS_TOP, 27, CLK_IS_CRITICAL, 0),
-       GATE(CLK_MAU_EPLL, "mau_epll", "mout_user_mau_epll",
-                       SRC_MASK_TOP7, 20, CLK_SET_RATE_PARENT, 0),
 };
 
 static const struct samsung_mux_clock exynos5420_mux_clks[] __initconst = {
@@ -577,8 +575,13 @@ static const struct samsung_div_clock exynos5420_div_clks[] __initconst = {
 
 static const struct samsung_gate_clock exynos5420_gate_clks[] __initconst = {
        GATE(CLK_SECKEY, "seckey", "aclk66_psgen", GATE_BUS_PERIS1, 1, 0, 0),
+       /* Maudio Block */
        GATE(CLK_MAU_EPLL, "mau_epll", "mout_mau_epll_clk",
                        SRC_MASK_TOP7, 20, CLK_SET_RATE_PARENT, 0),
+       GATE(CLK_SCLK_MAUDIO0, "sclk_maudio0", "dout_maudio0",
+               GATE_TOP_SCLK_MAU, 0, CLK_SET_RATE_PARENT, 0),
+       GATE(CLK_SCLK_MAUPCM0, "sclk_maupcm0", "dout_maupcm0",
+               GATE_TOP_SCLK_MAU, 1, CLK_SET_RATE_PARENT, 0),
 };
 
 static const struct samsung_mux_clock exynos5x_mux_clks[] __initconst = {
@@ -890,9 +893,6 @@ static const struct samsung_div_clock exynos5x_div_clks[] __initconst = {
        /* GSCL Block */
        DIV(0, "dout_gscl_blk_333", "aclk333_432_gscl", DIV2_RATIO0, 6, 2),
 
-       /* MSCL Block */
-       DIV(0, "dout_mscl_blk", "aclk400_mscl", DIV2_RATIO0, 28, 2),
-
        /* PSGEN */
        DIV(0, "dout_gen_blk", "mout_user_aclk266", DIV2_RATIO0, 8, 1),
        DIV(0, "dout_jpg_blk", "aclk166", DIV2_RATIO0, 20, 1),
@@ -1017,12 +1017,6 @@ static const struct samsung_gate_clock exynos5x_gate_clks[] __initconst = {
        GATE(CLK_SCLK_DP1, "sclk_dp1", "dout_dp1",
                        GATE_TOP_SCLK_DISP1, 20, CLK_SET_RATE_PARENT, 0),
 
-       /* Maudio Block */
-       GATE(CLK_SCLK_MAUDIO0, "sclk_maudio0", "dout_maudio0",
-               GATE_TOP_SCLK_MAU, 0, CLK_SET_RATE_PARENT, 0),
-       GATE(CLK_SCLK_MAUPCM0, "sclk_maupcm0", "dout_maupcm0",
-               GATE_TOP_SCLK_MAU, 1, CLK_SET_RATE_PARENT, 0),
-
        /* FSYS Block */
        GATE(CLK_TSI, "tsi", "aclk200_fsys", GATE_BUS_FSYS0, 0, 0, 0),
        GATE(CLK_PDMA0, "pdma0", "aclk200_fsys", GATE_BUS_FSYS0, 1, 0, 0),
@@ -1162,17 +1156,6 @@ static const struct samsung_gate_clock exynos5x_gate_clks[] __initconst = {
        GATE(CLK_FIMC_LITE3, "fimc_lite3", "aclk333_432_gscl",
                        GATE_IP_GSCL1, 17, 0, 0),
 
-       /* MSCL Block */
-       GATE(CLK_MSCL0, "mscl0", "aclk400_mscl", GATE_IP_MSCL, 0, 0, 0),
-       GATE(CLK_MSCL1, "mscl1", "aclk400_mscl", GATE_IP_MSCL, 1, 0, 0),
-       GATE(CLK_MSCL2, "mscl2", "aclk400_mscl", GATE_IP_MSCL, 2, 0, 0),
-       GATE(CLK_SMMU_MSCL0, "smmu_mscl0", "dout_mscl_blk",
-                       GATE_IP_MSCL, 8, 0, 0),
-       GATE(CLK_SMMU_MSCL1, "smmu_mscl1", "dout_mscl_blk",
-                       GATE_IP_MSCL, 9, 0, 0),
-       GATE(CLK_SMMU_MSCL2, "smmu_mscl2", "dout_mscl_blk",
-                       GATE_IP_MSCL, 10, 0, 0),
-
        /* ISP */
        GATE(CLK_SCLK_UART_ISP, "sclk_uart_isp", "dout_uart_isp",
                        GATE_TOP_SCLK_ISP, 0, CLK_SET_RATE_PARENT, 0),
@@ -1281,32 +1264,103 @@ static struct exynos5_subcmu_reg_dump exynos5x_mfc_suspend_regs[] = {
        { DIV4_RATIO, 0, 0x3 },                 /* DIV dout_mfc_blk */
 };
 
-static const struct exynos5_subcmu_info exynos5x_subcmus[] = {
-       {
-               .div_clks       = exynos5x_disp_div_clks,
-               .nr_div_clks    = ARRAY_SIZE(exynos5x_disp_div_clks),
-               .gate_clks      = exynos5x_disp_gate_clks,
-               .nr_gate_clks   = ARRAY_SIZE(exynos5x_disp_gate_clks),
-               .suspend_regs   = exynos5x_disp_suspend_regs,
-               .nr_suspend_regs = ARRAY_SIZE(exynos5x_disp_suspend_regs),
-               .pd_name        = "DISP",
-       }, {
-               .div_clks       = exynos5x_gsc_div_clks,
-               .nr_div_clks    = ARRAY_SIZE(exynos5x_gsc_div_clks),
-               .gate_clks      = exynos5x_gsc_gate_clks,
-               .nr_gate_clks   = ARRAY_SIZE(exynos5x_gsc_gate_clks),
-               .suspend_regs   = exynos5x_gsc_suspend_regs,
-               .nr_suspend_regs = ARRAY_SIZE(exynos5x_gsc_suspend_regs),
-               .pd_name        = "GSC",
-       }, {
-               .div_clks       = exynos5x_mfc_div_clks,
-               .nr_div_clks    = ARRAY_SIZE(exynos5x_mfc_div_clks),
-               .gate_clks      = exynos5x_mfc_gate_clks,
-               .nr_gate_clks   = ARRAY_SIZE(exynos5x_mfc_gate_clks),
-               .suspend_regs   = exynos5x_mfc_suspend_regs,
-               .nr_suspend_regs = ARRAY_SIZE(exynos5x_mfc_suspend_regs),
-               .pd_name        = "MFC",
-       },
+static const struct samsung_gate_clock exynos5x_mscl_gate_clks[] __initconst = {
+       /* MSCL Block */
+       GATE(CLK_MSCL0, "mscl0", "aclk400_mscl", GATE_IP_MSCL, 0, 0, 0),
+       GATE(CLK_MSCL1, "mscl1", "aclk400_mscl", GATE_IP_MSCL, 1, 0, 0),
+       GATE(CLK_MSCL2, "mscl2", "aclk400_mscl", GATE_IP_MSCL, 2, 0, 0),
+       GATE(CLK_SMMU_MSCL0, "smmu_mscl0", "dout_mscl_blk",
+                       GATE_IP_MSCL, 8, 0, 0),
+       GATE(CLK_SMMU_MSCL1, "smmu_mscl1", "dout_mscl_blk",
+                       GATE_IP_MSCL, 9, 0, 0),
+       GATE(CLK_SMMU_MSCL2, "smmu_mscl2", "dout_mscl_blk",
+                       GATE_IP_MSCL, 10, 0, 0),
+};
+
+static const struct samsung_div_clock exynos5x_mscl_div_clks[] __initconst = {
+       DIV(0, "dout_mscl_blk", "aclk400_mscl", DIV2_RATIO0, 28, 2),
+};
+
+static struct exynos5_subcmu_reg_dump exynos5x_mscl_suspend_regs[] = {
+       { GATE_IP_MSCL, 0xffffffff, 0xffffffff }, /* MSCL gates */
+       { SRC_TOP3, 0, BIT(4) },                /* MUX mout_user_aclk400_mscl */
+       { DIV2_RATIO0, 0, 0x30000000 },         /* DIV dout_mscl_blk */
+};
+
+static const struct samsung_gate_clock exynos5800_mau_gate_clks[] __initconst = {
+       GATE(CLK_MAU_EPLL, "mau_epll", "mout_user_mau_epll",
+                       SRC_MASK_TOP7, 20, CLK_SET_RATE_PARENT, 0),
+       GATE(CLK_SCLK_MAUDIO0, "sclk_maudio0", "dout_maudio0",
+               GATE_TOP_SCLK_MAU, 0, CLK_SET_RATE_PARENT, 0),
+       GATE(CLK_SCLK_MAUPCM0, "sclk_maupcm0", "dout_maupcm0",
+               GATE_TOP_SCLK_MAU, 1, CLK_SET_RATE_PARENT, 0),
+};
+
+static struct exynos5_subcmu_reg_dump exynos5800_mau_suspend_regs[] = {
+       { SRC_TOP9, 0, BIT(8) },        /* MUX mout_user_mau_epll */
+};
+
+static const struct exynos5_subcmu_info exynos5x_disp_subcmu = {
+       .div_clks       = exynos5x_disp_div_clks,
+       .nr_div_clks    = ARRAY_SIZE(exynos5x_disp_div_clks),
+       .gate_clks      = exynos5x_disp_gate_clks,
+       .nr_gate_clks   = ARRAY_SIZE(exynos5x_disp_gate_clks),
+       .suspend_regs   = exynos5x_disp_suspend_regs,
+       .nr_suspend_regs = ARRAY_SIZE(exynos5x_disp_suspend_regs),
+       .pd_name        = "DISP",
+};
+
+static const struct exynos5_subcmu_info exynos5x_gsc_subcmu = {
+       .div_clks       = exynos5x_gsc_div_clks,
+       .nr_div_clks    = ARRAY_SIZE(exynos5x_gsc_div_clks),
+       .gate_clks      = exynos5x_gsc_gate_clks,
+       .nr_gate_clks   = ARRAY_SIZE(exynos5x_gsc_gate_clks),
+       .suspend_regs   = exynos5x_gsc_suspend_regs,
+       .nr_suspend_regs = ARRAY_SIZE(exynos5x_gsc_suspend_regs),
+       .pd_name        = "GSC",
+};
+
+static const struct exynos5_subcmu_info exynos5x_mfc_subcmu = {
+       .div_clks       = exynos5x_mfc_div_clks,
+       .nr_div_clks    = ARRAY_SIZE(exynos5x_mfc_div_clks),
+       .gate_clks      = exynos5x_mfc_gate_clks,
+       .nr_gate_clks   = ARRAY_SIZE(exynos5x_mfc_gate_clks),
+       .suspend_regs   = exynos5x_mfc_suspend_regs,
+       .nr_suspend_regs = ARRAY_SIZE(exynos5x_mfc_suspend_regs),
+       .pd_name        = "MFC",
+};
+
+static const struct exynos5_subcmu_info exynos5x_mscl_subcmu = {
+       .div_clks       = exynos5x_mscl_div_clks,
+       .nr_div_clks    = ARRAY_SIZE(exynos5x_mscl_div_clks),
+       .gate_clks      = exynos5x_mscl_gate_clks,
+       .nr_gate_clks   = ARRAY_SIZE(exynos5x_mscl_gate_clks),
+       .suspend_regs   = exynos5x_mscl_suspend_regs,
+       .nr_suspend_regs = ARRAY_SIZE(exynos5x_mscl_suspend_regs),
+       .pd_name        = "MSC",
+};
+
+static const struct exynos5_subcmu_info exynos5800_mau_subcmu = {
+       .gate_clks      = exynos5800_mau_gate_clks,
+       .nr_gate_clks   = ARRAY_SIZE(exynos5800_mau_gate_clks),
+       .suspend_regs   = exynos5800_mau_suspend_regs,
+       .nr_suspend_regs = ARRAY_SIZE(exynos5800_mau_suspend_regs),
+       .pd_name        = "MAU",
+};
+
+static const struct exynos5_subcmu_info *exynos5x_subcmus[] = {
+       &exynos5x_disp_subcmu,
+       &exynos5x_gsc_subcmu,
+       &exynos5x_mfc_subcmu,
+       &exynos5x_mscl_subcmu,
+};
+
+static const struct exynos5_subcmu_info *exynos5800_subcmus[] = {
+       &exynos5x_disp_subcmu,
+       &exynos5x_gsc_subcmu,
+       &exynos5x_mfc_subcmu,
+       &exynos5x_mscl_subcmu,
+       &exynos5800_mau_subcmu,
 };
 
 static const struct samsung_pll_rate_table exynos5420_pll2550x_24mhz_tbl[] __initconst = {
@@ -1539,11 +1593,17 @@ static void __init exynos5x_clk_init(struct device_node *np,
        samsung_clk_extended_sleep_init(reg_base,
                exynos5x_clk_regs, ARRAY_SIZE(exynos5x_clk_regs),
                exynos5420_set_clksrc, ARRAY_SIZE(exynos5420_set_clksrc));
-       if (soc == EXYNOS5800)
+
+       if (soc == EXYNOS5800) {
                samsung_clk_sleep_init(reg_base, exynos5800_clk_regs,
                                       ARRAY_SIZE(exynos5800_clk_regs));
-       exynos5_subcmus_init(ctx, ARRAY_SIZE(exynos5x_subcmus),
-                            exynos5x_subcmus);
+
+               exynos5_subcmus_init(ctx, ARRAY_SIZE(exynos5800_subcmus),
+                                    exynos5800_subcmus);
+       } else {
+               exynos5_subcmus_init(ctx, ARRAY_SIZE(exynos5x_subcmus),
+                                    exynos5x_subcmus);
+       }
 
        samsung_clk_of_add_provider(np, ctx);
 }
index 5c50e723ecae7e945c85da36eacf514ffc71d81c..1a191eeeebbab915705bca2284c4cdbeba22bbd2 100644 (file)
@@ -38,7 +38,7 @@ static unsigned long clk_peri_cnt_clk_recalc_rate(struct clk_hw *hwclk,
        if (socfpgaclk->fixed_div) {
                div = socfpgaclk->fixed_div;
        } else {
-               if (!socfpgaclk->bypass_reg)
+               if (socfpgaclk->hw.reg)
                        div = ((readl(socfpgaclk->hw.reg) & 0x7ff) + 1);
        }
 
index 23e0a356f16754083a981158a8a6bf2508e97e57..ad72b3f42ffa06d413b7d2f5a73a5faa00458a71 100644 (file)
@@ -1163,6 +1163,7 @@ static int fsl_dma_chan_probe(struct fsldma_device *fdev,
        switch (chan->feature & FSL_DMA_IP_MASK) {
        case FSL_DMA_IP_85XX:
                chan->toggle_ext_pause = fsl_chan_toggle_ext_pause;
+               /* Fall through */
        case FSL_DMA_IP_83XX:
                chan->toggle_ext_start = fsl_chan_toggle_ext_start;
                chan->set_src_loop_size = fsl_chan_set_src_loop_size;
index 567fb98c0892740a8921a18542514fdb84b57fc0..9762dd6d99fa85181d542703449f7f12a5432b58 100644 (file)
@@ -363,7 +363,7 @@ struct gpio_desc *of_find_gpio(struct device *dev, const char *con_id,
        /* Special handling for SPI GPIOs if used */
        if (IS_ERR(desc))
                desc = of_find_spi_gpio(dev, con_id, &of_flags);
-       if (IS_ERR(desc)) {
+       if (IS_ERR(desc) && PTR_ERR(desc) != -EPROBE_DEFER) {
                /* This quirk looks up flags and all */
                desc = of_find_spi_cs_gpio(dev, con_id, idx, flags);
                if (!IS_ERR(desc))
index f497003f119c993a55e18ac0c54fcf95c138a2be..cca749010cd00afe966ac43ae91ae35b756092aa 100644 (file)
@@ -1091,9 +1091,11 @@ static long gpio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
                if (test_bit(FLAG_ACTIVE_LOW, &desc->flags))
                        lineinfo.flags |= GPIOLINE_FLAG_ACTIVE_LOW;
                if (test_bit(FLAG_OPEN_DRAIN, &desc->flags))
-                       lineinfo.flags |= GPIOLINE_FLAG_OPEN_DRAIN;
+                       lineinfo.flags |= (GPIOLINE_FLAG_OPEN_DRAIN |
+                                          GPIOLINE_FLAG_IS_OUT);
                if (test_bit(FLAG_OPEN_SOURCE, &desc->flags))
-                       lineinfo.flags |= GPIOLINE_FLAG_OPEN_SOURCE;
+                       lineinfo.flags |= (GPIOLINE_FLAG_OPEN_SOURCE |
+                                          GPIOLINE_FLAG_IS_OUT);
 
                if (copy_to_user(ip, &lineinfo, sizeof(lineinfo)))
                        return -EFAULT;
@@ -1371,21 +1373,13 @@ int gpiochip_add_data_with_key(struct gpio_chip *chip, void *data,
        if (status)
                goto err_remove_from_list;
 
-       status = gpiochip_irqchip_init_valid_mask(chip);
-       if (status)
-               goto err_remove_from_list;
-
        status = gpiochip_alloc_valid_mask(chip);
        if (status)
-               goto err_remove_irqchip_mask;
-
-       status = gpiochip_add_irqchip(chip, lock_key, request_key);
-       if (status)
-               goto err_free_gpiochip_mask;
+               goto err_remove_from_list;
 
        status = of_gpiochip_add(chip);
        if (status)
-               goto err_remove_chip;
+               goto err_free_gpiochip_mask;
 
        status = gpiochip_init_valid_mask(chip);
        if (status)
@@ -1411,6 +1405,14 @@ int gpiochip_add_data_with_key(struct gpio_chip *chip, void *data,
 
        machine_gpiochip_add(chip);
 
+       status = gpiochip_irqchip_init_valid_mask(chip);
+       if (status)
+               goto err_remove_acpi_chip;
+
+       status = gpiochip_add_irqchip(chip, lock_key, request_key);
+       if (status)
+               goto err_remove_irqchip_mask;
+
        /*
         * By first adding the chardev, and then adding the device,
         * we get a device node entry in sysfs under
@@ -1422,21 +1424,21 @@ int gpiochip_add_data_with_key(struct gpio_chip *chip, void *data,
        if (gpiolib_initialized) {
                status = gpiochip_setup_dev(gdev);
                if (status)
-                       goto err_remove_acpi_chip;
+                       goto err_remove_irqchip;
        }
        return 0;
 
+err_remove_irqchip:
+       gpiochip_irqchip_remove(chip);
+err_remove_irqchip_mask:
+       gpiochip_irqchip_free_valid_mask(chip);
 err_remove_acpi_chip:
        acpi_gpiochip_remove(chip);
 err_remove_of_chip:
        gpiochip_free_hogs(chip);
        of_gpiochip_remove(chip);
-err_remove_chip:
-       gpiochip_irqchip_remove(chip);
 err_free_gpiochip_mask:
        gpiochip_free_valid_mask(chip);
-err_remove_irqchip_mask:
-       gpiochip_irqchip_free_valid_mask(chip);
 err_remove_from_list:
        spin_lock_irqsave(&gpio_lock, flags);
        list_del(&gdev->list);
index 4e4094f842e728f6705486010ce6e94fd9605377..8b26c970a3cb1f364c1595c8a394daf44420d74d 100644 (file)
@@ -1143,6 +1143,9 @@ static int amdgpu_cs_process_syncobj_out_dep(struct amdgpu_cs_parser *p,
        num_deps = chunk->length_dw * 4 /
                sizeof(struct drm_amdgpu_cs_chunk_sem);
 
+       if (p->post_deps)
+               return -EINVAL;
+
        p->post_deps = kmalloc_array(num_deps, sizeof(*p->post_deps),
                                     GFP_KERNEL);
        p->num_post_deps = 0;
@@ -1166,8 +1169,7 @@ static int amdgpu_cs_process_syncobj_out_dep(struct amdgpu_cs_parser *p,
 
 
 static int amdgpu_cs_process_syncobj_timeline_out_dep(struct amdgpu_cs_parser *p,
-                                                     struct amdgpu_cs_chunk
-                                                     *chunk)
+                                                     struct amdgpu_cs_chunk *chunk)
 {
        struct drm_amdgpu_cs_chunk_syncobj *syncobj_deps;
        unsigned num_deps;
@@ -1177,6 +1179,9 @@ static int amdgpu_cs_process_syncobj_timeline_out_dep(struct amdgpu_cs_parser *p
        num_deps = chunk->length_dw * 4 /
                sizeof(struct drm_amdgpu_cs_chunk_syncobj);
 
+       if (p->post_deps)
+               return -EINVAL;
+
        p->post_deps = kmalloc_array(num_deps, sizeof(*p->post_deps),
                                     GFP_KERNEL);
        p->num_post_deps = 0;
index 04b8ac4432c700ca92d877879c664862ab20ffaf..4ea67f94cae2417ad0269e187fe7809ca3b200bf 100644 (file)
@@ -604,6 +604,10 @@ static void gfx_v9_0_check_if_need_gfxoff(struct amdgpu_device *adev)
                    (adev->gfx.rlc_feature_version < 1) ||
                    !adev->gfx.rlc.is_rlc_v2_1)
                        adev->pm.pp_feature &= ~PP_GFXOFF_MASK;
+               if (adev->pm.pp_feature & PP_GFXOFF_MASK)
+                       adev->pg_flags |= AMD_PG_SUPPORT_GFX_PG |
+                               AMD_PG_SUPPORT_CP |
+                               AMD_PG_SUPPORT_RLC_SMU_HS;
                break;
        default:
                break;
index 662612f89c70b5f2990a111aa740d350541a7127..9922bce3fd89e1362de3f60ed733333a0a7593c5 100644 (file)
@@ -552,7 +552,6 @@ static int nv_common_early_init(void *handle)
                        AMD_CG_SUPPORT_BIF_LS;
                adev->pg_flags = AMD_PG_SUPPORT_VCN |
                        AMD_PG_SUPPORT_VCN_DPG |
-                       AMD_PG_SUPPORT_MMHUB |
                        AMD_PG_SUPPORT_ATHUB;
                adev->external_rev_id = adev->rev_id + 0x1;
                break;
index 23265414d44867b81c36d85f1ef87e67013ca95f..04fbf05d7176b4276c5876382f7dabd6b8e4e6d6 100644 (file)
@@ -992,11 +992,6 @@ static int soc15_common_early_init(void *handle)
 
                        adev->pg_flags = AMD_PG_SUPPORT_SDMA | AMD_PG_SUPPORT_VCN;
                }
-
-               if (adev->pm.pp_feature & PP_GFXOFF_MASK)
-                       adev->pg_flags |= AMD_PG_SUPPORT_GFX_PG |
-                               AMD_PG_SUPPORT_CP |
-                               AMD_PG_SUPPORT_RLC_SMU_HS;
                break;
        default:
                /* FIXME: not supported yet */
index 4a29f72334d0fa88d738a93f5bd3778c30a81615..45be7a2132bb3b0f548004f38ee8e542608d534d 100644 (file)
@@ -3131,13 +3131,25 @@ static enum dc_color_depth
 convert_color_depth_from_display_info(const struct drm_connector *connector,
                                      const struct drm_connector_state *state)
 {
-       uint32_t bpc = connector->display_info.bpc;
+       uint8_t bpc = (uint8_t)connector->display_info.bpc;
+
+       /* Assume 8 bpc by default if no bpc is specified. */
+       bpc = bpc ? bpc : 8;
 
        if (!state)
                state = connector->state;
 
        if (state) {
-               bpc = state->max_bpc;
+               /*
+                * Cap display bpc based on the user requested value.
+                *
+                * The value for state->max_bpc may not correctly updated
+                * depending on when the connector gets added to the state
+                * or if this was called outside of atomic check, so it
+                * can't be used directly.
+                */
+               bpc = min(bpc, state->max_requested_bpc);
+
                /* Round down to the nearest even number. */
                bpc = bpc - (bpc & 1);
        }
index a0f52c86d8c7efa608221d4f56627894cfd2a244..a78b2e295895070a8d12940f3e8847ba61fd76e0 100644 (file)
@@ -907,8 +907,6 @@ struct smu_funcs
        ((smu)->funcs->register_irq_handler ? (smu)->funcs->register_irq_handler(smu) : 0)
 #define smu_set_azalia_d3_pme(smu) \
        ((smu)->funcs->set_azalia_d3_pme ? (smu)->funcs->set_azalia_d3_pme((smu)) : 0)
-#define smu_get_uclk_dpm_states(smu, clocks_in_khz, num_states) \
-       ((smu)->ppt_funcs->get_uclk_dpm_states ? (smu)->ppt_funcs->get_uclk_dpm_states((smu), (clocks_in_khz), (num_states)) : 0)
 #define smu_get_max_sustainable_clocks_by_dc(smu, max_clocks) \
        ((smu)->funcs->get_max_sustainable_clocks_by_dc ? (smu)->funcs->get_max_sustainable_clocks_by_dc((smu), (max_clocks)) : 0)
 #define smu_get_uclk_dpm_states(smu, clocks_in_khz, num_states) \
index 5fde5cf65b4240a7428e3c89be0dabc0ea12902f..53097961bf2b7239b4076e924e7e5ba6f263cdc6 100644 (file)
@@ -326,7 +326,8 @@ static int smu_v11_0_setup_pptable(struct smu_context *smu)
        struct amdgpu_device *adev = smu->adev;
        const struct smc_firmware_header_v1_0 *hdr;
        int ret, index;
-       uint32_t size;
+       uint32_t size = 0;
+       uint16_t atom_table_size;
        uint8_t frev, crev;
        void *table;
        uint16_t version_major, version_minor;
@@ -354,10 +355,11 @@ static int smu_v11_0_setup_pptable(struct smu_context *smu)
                index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,
                                                    powerplayinfo);
 
-               ret = smu_get_atom_data_table(smu, index, (uint16_t *)&size, &frev, &crev,
+               ret = smu_get_atom_data_table(smu, index, &atom_table_size, &frev, &crev,
                                              (uint8_t **)&table);
                if (ret)
                        return ret;
+               size = atom_table_size;
        }
 
        if (!smu->smu_table.power_play_table)
index 5a118984de33d558f082855e08f2c01df0abcb3d..a0eabc134dd6943f482302470caac50778ae07e3 100644 (file)
@@ -8,6 +8,7 @@
 #include <linux/iommu.h>
 #include <linux/of_device.h>
 #include <linux/of_graph.h>
+#include <linux/of_reserved_mem.h>
 #include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
 #ifdef CONFIG_DEBUG_FS
@@ -143,6 +144,12 @@ static int komeda_parse_dt(struct device *dev, struct komeda_dev *mdev)
                return mdev->irq;
        }
 
+       /* Get the optional framebuffer memory resource */
+       ret = of_reserved_mem_device_init(dev);
+       if (ret && ret != -ENODEV)
+               return ret;
+       ret = 0;
+
        for_each_available_child_of_node(np, child) {
                if (of_node_cmp(child->name, "pipeline") == 0) {
                        ret = komeda_parse_pipe_dt(mdev, child);
@@ -289,6 +296,8 @@ void komeda_dev_destroy(struct komeda_dev *mdev)
 
        mdev->n_pipelines = 0;
 
+       of_reserved_mem_device_release(dev);
+
        if (funcs && funcs->cleanup)
                funcs->cleanup(mdev);
 
index cd4d9f53ddef280340898e0c35ff6abdefdcf4a1..c9a1edb9a000a0b20a98a35ba4eaad1a07119358 100644 (file)
@@ -35,6 +35,25 @@ komeda_get_format_caps(struct komeda_format_caps_table *table,
        return NULL;
 }
 
+u32 komeda_get_afbc_format_bpp(const struct drm_format_info *info, u64 modifier)
+{
+       u32 bpp;
+
+       switch (info->format) {
+       case DRM_FORMAT_YUV420_8BIT:
+               bpp = 12;
+               break;
+       case DRM_FORMAT_YUV420_10BIT:
+               bpp = 15;
+               break;
+       default:
+               bpp = info->cpp[0] * 8;
+               break;
+       }
+
+       return bpp;
+}
+
 /* Two assumptions
  * 1. RGB always has YTR
  * 2. Tiled RGB always has SC
index 3631910d33b5e4a5e83db4140921cf432265c4ef..32273cf18f7c55e53f9d7ee37c9e42eb2238ea63 100644 (file)
@@ -97,6 +97,9 @@ const struct komeda_format_caps *
 komeda_get_format_caps(struct komeda_format_caps_table *table,
                       u32 fourcc, u64 modifier);
 
+u32 komeda_get_afbc_format_bpp(const struct drm_format_info *info,
+                              u64 modifier);
+
 u32 *komeda_get_layer_fourcc_list(struct komeda_format_caps_table *table,
                                  u32 layer_type, u32 *n_fmts);
 
index 3b0a70ed6aa0fb078748f82b69e44edc4d843860..1b01a625f40e36e96aef7312dee118226767526d 100644 (file)
@@ -43,7 +43,7 @@ komeda_fb_afbc_size_check(struct komeda_fb *kfb, struct drm_file *file,
        struct drm_framebuffer *fb = &kfb->base;
        const struct drm_format_info *info = fb->format;
        struct drm_gem_object *obj;
-       u32 alignment_w = 0, alignment_h = 0, alignment_header, n_blocks;
+       u32 alignment_w = 0, alignment_h = 0, alignment_header, n_blocks, bpp;
        u64 min_size;
 
        obj = drm_gem_object_lookup(file, mode_cmd->handles[0]);
@@ -88,8 +88,9 @@ komeda_fb_afbc_size_check(struct komeda_fb *kfb, struct drm_file *file,
        kfb->offset_payload = ALIGN(n_blocks * AFBC_HEADER_SIZE,
                                    alignment_header);
 
+       bpp = komeda_get_afbc_format_bpp(info, fb->modifier);
        kfb->afbc_size = kfb->offset_payload + n_blocks *
-                        ALIGN(info->cpp[0] * AFBC_SUPERBLK_PIXELS,
+                        ALIGN(bpp * AFBC_SUPERBLK_PIXELS / 8,
                               AFBC_SUPERBLK_ALIGNMENT);
        min_size = kfb->afbc_size + fb->offsets[0];
        if (min_size > obj->size) {
index 419a8b0e5de8f2fe96be3d9e022e73405eb406f2..d50e75f0b2bdce5c5bdf3daa6dcfcdff2f5e0c2a 100644 (file)
@@ -15,6 +15,7 @@
 #include <drm/drm_gem_framebuffer_helper.h>
 #include <drm/drm_irq.h>
 #include <drm/drm_vblank.h>
+#include <drm/drm_probe_helper.h>
 
 #include "komeda_dev.h"
 #include "komeda_framebuffer.h"
@@ -315,6 +316,8 @@ struct komeda_kms_dev *komeda_kms_attach(struct komeda_dev *mdev)
 
        drm->irq_enabled = true;
 
+       drm_kms_helper_poll_init(drm);
+
        err = drm_dev_register(drm, 0);
        if (err)
                goto cleanup_mode_config;
@@ -322,6 +325,7 @@ struct komeda_kms_dev *komeda_kms_attach(struct komeda_dev *mdev)
        return kms;
 
 cleanup_mode_config:
+       drm_kms_helper_poll_fini(drm);
        drm->irq_enabled = false;
        drm_mode_config_cleanup(drm);
        komeda_kms_cleanup_private_objs(kms);
@@ -338,6 +342,7 @@ void komeda_kms_detach(struct komeda_kms_dev *kms)
        drm->irq_enabled = false;
        mdev->funcs->disable_irq(mdev);
        drm_dev_unregister(drm);
+       drm_kms_helper_poll_fini(drm);
        component_unbind_all(mdev->dev, drm);
        komeda_kms_cleanup_private_objs(kms);
        drm_mode_config_cleanup(drm);
index 7925a176f90073763bf189cb0bee2482b8cf5c94..1cb1fa74cfbc97d15012d6beb2c0370ebd7f570c 100644 (file)
@@ -1465,8 +1465,8 @@ static void ddi_dotclock_get(struct intel_crtc_state *pipe_config)
        else if (intel_crtc_has_dp_encoder(pipe_config))
                dotclock = intel_dotclock_calculate(pipe_config->port_clock,
                                                    &pipe_config->dp_m_n);
-       else if (pipe_config->has_hdmi_sink && pipe_config->pipe_bpp == 36)
-               dotclock = pipe_config->port_clock * 2 / 3;
+       else if (pipe_config->has_hdmi_sink && pipe_config->pipe_bpp > 24)
+               dotclock = pipe_config->port_clock * 24 / pipe_config->pipe_bpp;
        else
                dotclock = pipe_config->port_clock;
 
index 1d58f7ec5d84b29229854d50df63abfc2683f357..f11979879e7bc094ccb4a0274e49eda960180a28 100644 (file)
@@ -829,7 +829,7 @@ struct intel_crtc_state {
 
        /*
         * Frequence the dpll for the port should run at. Differs from the
-        * adjusted dotclock e.g. for DP or 12bpc hdmi mode. This is also
+        * adjusted dotclock e.g. for DP or 10/12bpc hdmi mode. This is also
         * already multiplied by pixel_multiplier.
         */
        int port_clock;
index 95fdbd0fbcace01f26e3c1c393210ba09e60a952..945bc20f1d33f0d5aada0a7d9d7c0e52fb15c28a 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/of_address.h>
 #include <linux/of_platform.h>
 #include <linux/pm_runtime.h>
+#include <linux/dma-mapping.h>
 
 #include "mtk_drm_crtc.h"
 #include "mtk_drm_ddp.h"
@@ -213,6 +214,7 @@ static int mtk_drm_kms_init(struct drm_device *drm)
        struct mtk_drm_private *private = drm->dev_private;
        struct platform_device *pdev;
        struct device_node *np;
+       struct device *dma_dev;
        int ret;
 
        if (!iommu_present(&platform_bus_type))
@@ -275,7 +277,29 @@ static int mtk_drm_kms_init(struct drm_device *drm)
                goto err_component_unbind;
        }
 
-       private->dma_dev = &pdev->dev;
+       dma_dev = &pdev->dev;
+       private->dma_dev = dma_dev;
+
+       /*
+        * Configure the DMA segment size to make sure we get contiguous IOVA
+        * when importing PRIME buffers.
+        */
+       if (!dma_dev->dma_parms) {
+               private->dma_parms_allocated = true;
+               dma_dev->dma_parms =
+                       devm_kzalloc(drm->dev, sizeof(*dma_dev->dma_parms),
+                                    GFP_KERNEL);
+       }
+       if (!dma_dev->dma_parms) {
+               ret = -ENOMEM;
+               goto err_component_unbind;
+       }
+
+       ret = dma_set_max_seg_size(dma_dev, (unsigned int)DMA_BIT_MASK(32));
+       if (ret) {
+               dev_err(dma_dev, "Failed to set DMA segment size\n");
+               goto err_unset_dma_parms;
+       }
 
        /*
         * We don't use the drm_irq_install() helpers provided by the DRM
@@ -285,13 +309,16 @@ static int mtk_drm_kms_init(struct drm_device *drm)
        drm->irq_enabled = true;
        ret = drm_vblank_init(drm, MAX_CRTC);
        if (ret < 0)
-               goto err_component_unbind;
+               goto err_unset_dma_parms;
 
        drm_kms_helper_poll_init(drm);
        drm_mode_config_reset(drm);
 
        return 0;
 
+err_unset_dma_parms:
+       if (private->dma_parms_allocated)
+               dma_dev->dma_parms = NULL;
 err_component_unbind:
        component_unbind_all(drm->dev, drm);
 err_config_cleanup:
@@ -302,9 +329,14 @@ err_config_cleanup:
 
 static void mtk_drm_kms_deinit(struct drm_device *drm)
 {
+       struct mtk_drm_private *private = drm->dev_private;
+
        drm_kms_helper_poll_fini(drm);
        drm_atomic_helper_shutdown(drm);
 
+       if (private->dma_parms_allocated)
+               private->dma_dev->dma_parms = NULL;
+
        component_unbind_all(drm->dev, drm);
        drm_mode_config_cleanup(drm);
 }
@@ -320,6 +352,18 @@ static const struct file_operations mtk_drm_fops = {
        .compat_ioctl = drm_compat_ioctl,
 };
 
+/*
+ * We need to override this because the device used to import the memory is
+ * not dev->dev, as drm_gem_prime_import() expects.
+ */
+struct drm_gem_object *mtk_drm_gem_prime_import(struct drm_device *dev,
+                                               struct dma_buf *dma_buf)
+{
+       struct mtk_drm_private *private = dev->dev_private;
+
+       return drm_gem_prime_import_dev(dev, dma_buf, private->dma_dev);
+}
+
 static struct drm_driver mtk_drm_driver = {
        .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME |
                           DRIVER_ATOMIC,
@@ -331,7 +375,7 @@ static struct drm_driver mtk_drm_driver = {
        .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
        .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
        .gem_prime_export = drm_gem_prime_export,
-       .gem_prime_import = drm_gem_prime_import,
+       .gem_prime_import = mtk_drm_gem_prime_import,
        .gem_prime_get_sg_table = mtk_gem_prime_get_sg_table,
        .gem_prime_import_sg_table = mtk_gem_prime_import_sg_table,
        .gem_prime_mmap = mtk_drm_gem_mmap_buf,
@@ -524,12 +568,15 @@ static int mtk_drm_probe(struct platform_device *pdev)
                        comp = devm_kzalloc(dev, sizeof(*comp), GFP_KERNEL);
                        if (!comp) {
                                ret = -ENOMEM;
+                               of_node_put(node);
                                goto err_node;
                        }
 
                        ret = mtk_ddp_comp_init(dev, node, comp, comp_id, NULL);
-                       if (ret)
+                       if (ret) {
+                               of_node_put(node);
                                goto err_node;
+                       }
 
                        private->ddp_comp[comp_id] = comp;
                }
index 598ff3e7044652ef19dfe71420354e0f18b058c4..e03fea12ff5988de393ee6fc2165dce7189700c9 100644 (file)
@@ -51,6 +51,8 @@ struct mtk_drm_private {
        } commit;
 
        struct drm_atomic_state *suspend_state;
+
+       bool dma_parms_allocated;
 };
 
 extern struct platform_driver mtk_ddp_driver;
index b4e7404fe660e24937bde1e518533feecad376d9..a11637b0f6ccf43cc39c417dc64a8fb349815a22 100644 (file)
@@ -40,8 +40,7 @@ nvkm_i2c_aux_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
                u8 *ptr = msg->buf;
 
                while (remaining) {
-                       u8 cnt = (remaining > 16) ? 16 : remaining;
-                       u8 cmd;
+                       u8 cnt, retries, cmd;
 
                        if (msg->flags & I2C_M_RD)
                                cmd = 1;
@@ -51,10 +50,19 @@ nvkm_i2c_aux_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
                        if (mcnt || remaining > 16)
                                cmd |= 4; /* MOT */
 
-                       ret = aux->func->xfer(aux, true, cmd, msg->addr, ptr, &cnt);
-                       if (ret < 0) {
-                               nvkm_i2c_aux_release(aux);
-                               return ret;
+                       for (retries = 0, cnt = 0;
+                            retries < 32 && !cnt;
+                            retries++) {
+                               cnt = min_t(u8, remaining, 16);
+                               ret = aux->func->xfer(aux, true, cmd,
+                                                     msg->addr, ptr, &cnt);
+                               if (ret < 0)
+                                       goto out;
+                       }
+                       if (!cnt) {
+                               AUX_TRACE(aux, "no data after 32 retries");
+                               ret = -EIO;
+                               goto out;
                        }
 
                        ptr += cnt;
@@ -64,8 +72,10 @@ nvkm_i2c_aux_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
                msg++;
        }
 
+       ret = num;
+out:
        nvkm_i2c_aux_release(aux);
-       return num;
+       return ret;
 }
 
 static u32
index 288c59dae56ad9326d3e50699deb8ec0445d071d..1bad0a2cc5c6362045c29439bc2a3e2cf9d9ccc1 100644 (file)
@@ -669,7 +669,7 @@ static int pdev_probe(struct platform_device *pdev)
        if (omapdss_is_initialized() == false)
                return -EPROBE_DEFER;
 
-       ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
+       ret = dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
        if (ret) {
                dev_err(&pdev->dev, "Failed to set the DMA mask\n");
                return ret;
index 1c62578590f462fbc4ab8fb1e102c6bfef57b8f5..082d02c840249c49e79de11465feb44e3fe28950 100644 (file)
@@ -673,10 +673,8 @@ static int rcar_lvds_parse_dt_companion(struct rcar_lvds *lvds)
 
        /* Locate the companion LVDS encoder for dual-link operation, if any. */
        companion = of_parse_phandle(dev->of_node, "renesas,companion", 0);
-       if (!companion) {
-               dev_err(dev, "Companion LVDS encoder not found\n");
-               return -ENXIO;
-       }
+       if (!companion)
+               return 0;
 
        /*
         * Sanity check: the companion encoder must have the same compatible
index 64c43ee6bd92ffe01938afa69e9683e897e7fca6..df0cc8f46d7bdcc63578b30e0f97cb2f1e36f409 100644 (file)
@@ -314,6 +314,7 @@ static void sun4i_tcon0_mode_set_dithering(struct sun4i_tcon *tcon,
                /* R and B components are only 5 bits deep */
                val |= SUN4I_TCON0_FRM_CTL_MODE_R;
                val |= SUN4I_TCON0_FRM_CTL_MODE_B;
+               /* Fall through */
        case MEDIA_BUS_FMT_RGB666_1X18:
        case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG:
                /* Fall through: enable dithering */
index a1fc8b520985506a5f050af1d9d3eb2729f120ea..b889ad3e86e179fa8b3f404aaaa28855d97be21b 100644 (file)
@@ -993,6 +993,7 @@ static ssize_t sun6i_dsi_transfer(struct mipi_dsi_host *host,
                        ret = sun6i_dsi_dcs_read(dsi, msg);
                        break;
                }
+               /* Else, fall through */
 
        default:
                ret = -EINVAL;
index 2310c96ccf4a6a9d85fb81bd36b8e83308d7930d..db1b55df0d1319c21b382fd8430e95f1821e3415 100644 (file)
@@ -1153,8 +1153,6 @@ static unsigned int cp2112_gpio_irq_startup(struct irq_data *d)
 
        INIT_DELAYED_WORK(&dev->gpio_poll_worker, cp2112_gpio_poll_callback);
 
-       cp2112_gpio_direction_input(gc, d->hwirq);
-
        if (!dev->gpio_poll) {
                dev->gpio_poll = true;
                schedule_delayed_work(&dev->gpio_poll_worker, 0);
@@ -1204,6 +1202,12 @@ static int __maybe_unused cp2112_allocate_irq(struct cp2112_device *dev,
                return PTR_ERR(dev->desc[pin]);
        }
 
+       ret = cp2112_gpio_direction_input(&dev->gc, pin);
+       if (ret < 0) {
+               dev_err(dev->gc.parent, "Failed to set GPIO to input dir\n");
+               goto err_desc;
+       }
+
        ret = gpiochip_lock_as_irq(&dev->gc, pin);
        if (ret) {
                dev_err(dev->gc.parent, "Failed to lock GPIO as interrupt\n");
index 21268c9fa71a6654a3e0bd6ba73a6570d4b4b1bd..0179f7ed77e5b13f852f4c4fb3fa9619f1c15677 100644 (file)
@@ -3749,30 +3749,8 @@ static const struct hid_device_id hidpp_devices[] = {
 
        { L27MHZ_DEVICE(HID_ANY_ID) },
 
-       { /* Logitech G203/Prodigy Gaming Mouse */
-         HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC084) },
-       { /* Logitech G302 Gaming Mouse */
-         HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC07F) },
-       { /* Logitech G303 Gaming Mouse */
-         HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC080) },
-       { /* Logitech G400 Gaming Mouse */
-         HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC07E) },
        { /* Logitech G403 Wireless Gaming Mouse over USB */
          HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC082) },
-       { /* Logitech G403 Gaming Mouse */
-         HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC083) },
-       { /* Logitech G403 Hero Gaming Mouse over USB */
-         HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC08F) },
-       { /* Logitech G502 Proteus Core Gaming Mouse */
-         HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC07D) },
-       { /* Logitech G502 Proteus Spectrum Gaming Mouse over USB */
-         HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC332) },
-       { /* Logitech G502 Hero Gaming Mouse over USB */
-         HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC08B) },
-       { /* Logitech G700 Gaming Mouse over USB */
-         HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC06B) },
-       { /* Logitech G700s Gaming Mouse over USB */
-         HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC07C) },
        { /* Logitech G703 Gaming Mouse over USB */
          HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC087) },
        { /* Logitech G703 Hero Gaming Mouse over USB */
index 1065692f90e20d528be161a0059c2f45ccb0b22c..5792a104000a915c55a2eae60354b47309433237 100644 (file)
@@ -24,6 +24,7 @@
 #define ICL_MOBILE_DEVICE_ID   0x34FC
 #define SPT_H_DEVICE_ID                0xA135
 #define CML_LP_DEVICE_ID       0x02FC
+#define EHL_Ax_DEVICE_ID       0x4BB3
 
 #define        REVISION_ID_CHT_A0      0x6
 #define        REVISION_ID_CHT_Ax_SI   0x0
index aa80b4d3b740411ab8159f0c82d683d7c3d24d1c..279567baca3d95bd127256e84805a84f94f54a67 100644 (file)
@@ -33,6 +33,7 @@ static const struct pci_device_id ish_pci_tbl[] = {
        {PCI_DEVICE(PCI_VENDOR_ID_INTEL, ICL_MOBILE_DEVICE_ID)},
        {PCI_DEVICE(PCI_VENDOR_ID_INTEL, SPT_H_DEVICE_ID)},
        {PCI_DEVICE(PCI_VENDOR_ID_INTEL, CML_LP_DEVICE_ID)},
+       {PCI_DEVICE(PCI_VENDOR_ID_INTEL, EHL_Ax_DEVICE_ID)},
        {0, }
 };
 MODULE_DEVICE_TABLE(pci, ish_pci_tbl);
index 7a8ddc999a8e3b8fdb05c6e41ca17d20badbff7a..1713235d28cb01c1038b6fd1590849f684018510 100644 (file)
@@ -846,6 +846,8 @@ static int wacom_intuos_general(struct wacom_wac *wacom)
                y >>= 1;
                distance >>= 1;
        }
+       if (features->type == INTUOSHT2)
+               distance = features->distance_max - distance;
        input_report_abs(input, ABS_X, x);
        input_report_abs(input, ABS_Y, y);
        input_report_abs(input, ABS_DISTANCE, distance);
@@ -1059,7 +1061,7 @@ static int wacom_remote_irq(struct wacom_wac *wacom_wac, size_t len)
        input_report_key(input, BTN_BASE2, (data[11] & 0x02));
 
        if (data[12] & 0x80)
-               input_report_abs(input, ABS_WHEEL, (data[12] & 0x7f));
+               input_report_abs(input, ABS_WHEEL, (data[12] & 0x7f) - 1);
        else
                input_report_abs(input, ABS_WHEEL, 0);
 
@@ -1290,7 +1292,8 @@ static void wacom_intuos_pro2_bt_pen(struct wacom_wac *wacom)
                }
                if (wacom->tool[0]) {
                        input_report_abs(pen_input, ABS_PRESSURE, get_unaligned_le16(&frame[5]));
-                       if (wacom->features.type == INTUOSP2_BT) {
+                       if (wacom->features.type == INTUOSP2_BT ||
+                           wacom->features.type == INTUOSP2S_BT) {
                                input_report_abs(pen_input, ABS_DISTANCE,
                                                 range ? frame[13] : wacom->features.distance_max);
                        } else {
index 5f9505a087f61bbfd33172257a7d0bb6340140d9..23f358cb7f494c159e2ca9d74046b470b75673a1 100644 (file)
@@ -26,7 +26,7 @@
 
 static unsigned long virt_to_hvpfn(void *addr)
 {
-       unsigned long paddr;
+       phys_addr_t paddr;
 
        if (is_vmalloc_addr(addr))
                paddr = page_to_phys(vmalloc_to_page(addr)) +
index 362e70e9d145410f71dd14c1561a761195ac971c..fb16a622e8ab8dd9623e734baf5ef6b6f23d18ff 100644 (file)
@@ -146,8 +146,6 @@ struct hv_context {
         */
        u64 guestid;
 
-       void *tsc_page;
-
        struct hv_per_cpu_context __percpu *cpu_context;
 
        /*
index 19f1730a4f2442a175536f290ae40941d3bf954c..a68d0ccf67a431f915822b1f943800c8c3655b8c 100644 (file)
@@ -4724,10 +4724,14 @@ static int __init cma_init(void)
        if (ret)
                goto err;
 
-       cma_configfs_init();
+       ret = cma_configfs_init();
+       if (ret)
+               goto err_ib;
 
        return 0;
 
+err_ib:
+       ib_unregister_client(&cma_client);
 err:
        unregister_netdevice_notifier(&cma_nb);
        ib_sa_unregister_client(&sa_client);
index b79890739a2c6b14f0d653c1e6e5a61ec3747680..af8c85d18e62ffde7e7bc0cf78b2a8d294a27f76 100644 (file)
@@ -149,13 +149,11 @@ static bool auto_mode_match(struct ib_qp *qp, struct rdma_counter *counter,
        struct auto_mode_param *param = &counter->mode.param;
        bool match = true;
 
-       if (rdma_is_kernel_res(&counter->res) != rdma_is_kernel_res(&qp->res))
+       if (!rdma_is_visible_in_pid_ns(&qp->res))
                return false;
 
-       /* Ensure that counter belong to right PID */
-       if (!rdma_is_kernel_res(&counter->res) &&
-           !rdma_is_kernel_res(&qp->res) &&
-           (task_pid_vnr(counter->res.task) != current->pid))
+       /* Ensure that counter belongs to the right PID */
+       if (task_pid_nr(counter->res.task) != task_pid_nr(qp->res.task))
                return false;
 
        if (auto_mask & RDMA_COUNTER_MASK_QP_TYPE)
@@ -424,7 +422,7 @@ static struct ib_qp *rdma_counter_get_qp(struct ib_device *dev, u32 qp_num)
        return qp;
 
 err:
-       rdma_restrack_put(&qp->res);
+       rdma_restrack_put(res);
        return NULL;
 }
 
index 87d40d1ecdde8064ae36b03dce5963c3e9a390bc..020c269765584e9792ddb1f19c64a6971171f3c6 100644 (file)
@@ -382,8 +382,7 @@ static int fill_res_info(struct sk_buff *msg, struct ib_device *device)
        for (i = 0; i < RDMA_RESTRACK_MAX; i++) {
                if (!names[i])
                        continue;
-               curr = rdma_restrack_count(device, i,
-                                          task_active_pid_ns(current));
+               curr = rdma_restrack_count(device, i);
                ret = fill_res_info_entry(msg, names[i], curr);
                if (ret)
                        goto err;
index bddff426ee0f0d37dfb32a9e03f97dc9cde7a9ad..a07665f7ef8ceffa81d9dd1ede9b4c71e4c977b7 100644 (file)
@@ -107,10 +107,8 @@ void rdma_restrack_clean(struct ib_device *dev)
  * rdma_restrack_count() - the current usage of specific object
  * @dev:  IB device
  * @type: actual type of object to operate
- * @ns:   PID namespace
  */
-int rdma_restrack_count(struct ib_device *dev, enum rdma_restrack_type type,
-                       struct pid_namespace *ns)
+int rdma_restrack_count(struct ib_device *dev, enum rdma_restrack_type type)
 {
        struct rdma_restrack_root *rt = &dev->res[type];
        struct rdma_restrack_entry *e;
@@ -119,10 +117,9 @@ int rdma_restrack_count(struct ib_device *dev, enum rdma_restrack_type type,
 
        xa_lock(&rt->xa);
        xas_for_each(&xas, e, U32_MAX) {
-               if (ns == &init_pid_ns ||
-                   (!rdma_is_kernel_res(e) &&
-                    ns == task_active_pid_ns(e->task)))
-                       cnt++;
+               if (!rdma_is_visible_in_pid_ns(e))
+                       continue;
+               cnt++;
        }
        xa_unlock(&rt->xa);
        return cnt;
@@ -360,5 +357,7 @@ bool rdma_is_visible_in_pid_ns(struct rdma_restrack_entry *res)
         */
        if (rdma_is_kernel_res(res))
                return task_active_pid_ns(current) == &init_pid_ns;
-       return task_active_pid_ns(current) == task_active_pid_ns(res->task);
+
+       /* PID 0 means that resource is not found in current namespace */
+       return task_pid_vnr(res->task);
 }
index 08da840ed7eebc151b67a61b15626d90578dea54..56553668256f5e9279de8676ce3f2d443391db30 100644 (file)
@@ -379,14 +379,9 @@ EXPORT_SYMBOL(ib_umem_release);
 
 int ib_umem_page_count(struct ib_umem *umem)
 {
-       int i;
-       int n;
+       int i, n = 0;
        struct scatterlist *sg;
 
-       if (umem->is_odp)
-               return ib_umem_num_pages(umem);
-
-       n = 0;
        for_each_sg(umem->sg_head.sgl, sg, umem->nmap, i)
                n += sg_dma_len(sg) >> PAGE_SHIFT;
 
index 48b04d2f175f908e984c12fda163237cf56876b5..60c8f76aab33d9d7307bb57391736ace8a782dbd 100644 (file)
@@ -136,6 +136,13 @@ static int __send_message(struct bnxt_qplib_rcfw *rcfw, struct cmdq_base *req,
                spin_unlock_irqrestore(&cmdq->lock, flags);
                return -EBUSY;
        }
+
+       size = req->cmd_size;
+       /* change the cmd_size to the number of 16byte cmdq unit.
+        * req->cmd_size is modified here
+        */
+       bnxt_qplib_set_cmd_slots(req);
+
        memset(resp, 0, sizeof(*resp));
        crsqe->resp = (struct creq_qp_event *)resp;
        crsqe->resp->cookie = req->cookie;
@@ -150,7 +157,6 @@ static int __send_message(struct bnxt_qplib_rcfw *rcfw, struct cmdq_base *req,
 
        cmdq_ptr = (struct bnxt_qplib_cmdqe **)cmdq->pbl_ptr;
        preq = (u8 *)req;
-       size = req->cmd_size * BNXT_QPLIB_CMDQE_UNITS;
        do {
                /* Locate the next cmdq slot */
                sw_prod = HWQ_CMP(cmdq->prod, cmdq);
index 2138533bb64267e15e1efbea099ccdf084ce6ccd..dfeadc192e17401525de94f23080ba287ad21503 100644 (file)
@@ -55,9 +55,7 @@
        do {                                                            \
                memset(&(req), 0, sizeof((req)));                       \
                (req).opcode = CMDQ_BASE_OPCODE_##CMD;                  \
-               (req).cmd_size = (sizeof((req)) +                       \
-                               BNXT_QPLIB_CMDQE_UNITS - 1) /           \
-                               BNXT_QPLIB_CMDQE_UNITS;                 \
+               (req).cmd_size = sizeof((req));                         \
                (req).flags = cpu_to_le16(cmd_flags);                   \
        } while (0)
 
@@ -95,6 +93,13 @@ static inline u32 bnxt_qplib_cmdqe_cnt_per_pg(u32 depth)
                 BNXT_QPLIB_CMDQE_UNITS);
 }
 
+/* Set the cmd_size to a factor of CMDQE unit */
+static inline void bnxt_qplib_set_cmd_slots(struct cmdq_base *req)
+{
+       req->cmd_size = (req->cmd_size + BNXT_QPLIB_CMDQE_UNITS - 1) /
+                        BNXT_QPLIB_CMDQE_UNITS;
+}
+
 #define MAX_CMDQ_IDX(depth)            ((depth) - 1)
 
 static inline u32 bnxt_qplib_max_cmdq_idx_per_pg(u32 depth)
index 93613e5def9b7bd4492e65494abd4d420fc5a6c1..986c12153e62ecbe03e99a421355188fbf08c47f 100644 (file)
@@ -141,12 +141,14 @@ static ssize_t fault_opcodes_write(struct file *file, const char __user *buf,
        if (!data)
                return -ENOMEM;
        copy = min(len, datalen - 1);
-       if (copy_from_user(data, buf, copy))
-               return -EFAULT;
+       if (copy_from_user(data, buf, copy)) {
+               ret = -EFAULT;
+               goto free_data;
+       }
 
        ret = debugfs_file_get(file->f_path.dentry);
        if (unlikely(ret))
-               return ret;
+               goto free_data;
        ptr = data;
        token = ptr;
        for (ptr = data; *ptr; ptr = end + 1, token = ptr) {
@@ -195,6 +197,7 @@ static ssize_t fault_opcodes_write(struct file *file, const char __user *buf,
        ret = len;
 
        debugfs_file_put(file->f_path.dentry);
+free_data:
        kfree(data);
        return ret;
 }
@@ -214,7 +217,7 @@ static ssize_t fault_opcodes_read(struct file *file, char __user *buf,
                return -ENOMEM;
        ret = debugfs_file_get(file->f_path.dentry);
        if (unlikely(ret))
-               return ret;
+               goto free_data;
        bit = find_first_bit(fault->opcodes, bitsize);
        while (bit < bitsize) {
                zero = find_next_zero_bit(fault->opcodes, bitsize, bit);
@@ -232,6 +235,7 @@ static ssize_t fault_opcodes_read(struct file *file, char __user *buf,
        data[size - 1] = '\n';
        data[size] = '\0';
        ret = simple_read_from_buffer(buf, len, pos, data, size);
+free_data:
        kfree(data);
        return ret;
 }
index 996fc298207ea9f1520ce956a3e75e3119ca0240..6141f4edc6bfa00423b757631fa22aeb43485cd1 100644 (file)
@@ -2574,18 +2574,9 @@ void hfi1_kern_read_tid_flow_free(struct rvt_qp *qp)
        hfi1_kern_clear_hw_flow(priv->rcd, qp);
 }
 
-static bool tid_rdma_tid_err(struct hfi1_ctxtdata *rcd,
-                            struct hfi1_packet *packet, u8 rcv_type,
-                            u8 opcode)
+static bool tid_rdma_tid_err(struct hfi1_packet *packet, u8 rcv_type)
 {
        struct rvt_qp *qp = packet->qp;
-       struct hfi1_qp_priv *qpriv = qp->priv;
-       u32 ipsn;
-       struct ib_other_headers *ohdr = packet->ohdr;
-       struct rvt_ack_entry *e;
-       struct tid_rdma_request *req;
-       struct rvt_dev_info *rdi = ib_to_rvt(qp->ibqp.device);
-       u32 i;
 
        if (rcv_type >= RHF_RCV_TYPE_IB)
                goto done;
@@ -2602,41 +2593,9 @@ static bool tid_rdma_tid_err(struct hfi1_ctxtdata *rcd,
        if (rcv_type == RHF_RCV_TYPE_EAGER) {
                hfi1_restart_rc(qp, qp->s_last_psn + 1, 1);
                hfi1_schedule_send(qp);
-               goto done_unlock;
-       }
-
-       /*
-        * For TID READ response, error out QP after freeing the tid
-        * resources.
-        */
-       if (opcode == TID_OP(READ_RESP)) {
-               ipsn = mask_psn(be32_to_cpu(ohdr->u.tid_rdma.r_rsp.verbs_psn));
-               if (cmp_psn(ipsn, qp->s_last_psn) > 0 &&
-                   cmp_psn(ipsn, qp->s_psn) < 0) {
-                       hfi1_kern_read_tid_flow_free(qp);
-                       spin_unlock(&qp->s_lock);
-                       rvt_rc_error(qp, IB_WC_LOC_QP_OP_ERR);
-                       goto done;
-               }
-               goto done_unlock;
-       }
-
-       /*
-        * Error out the qp for TID RDMA WRITE
-        */
-       hfi1_kern_clear_hw_flow(qpriv->rcd, qp);
-       for (i = 0; i < rvt_max_atomic(rdi); i++) {
-               e = &qp->s_ack_queue[i];
-               if (e->opcode == TID_OP(WRITE_REQ)) {
-                       req = ack_to_tid_req(e);
-                       hfi1_kern_exp_rcv_clear_all(req);
-               }
        }
-       spin_unlock(&qp->s_lock);
-       rvt_rc_error(qp, IB_WC_LOC_LEN_ERR);
-       goto done;
 
-done_unlock:
+       /* Since no payload is delivered, just drop the packet */
        spin_unlock(&qp->s_lock);
 done:
        return true;
@@ -2687,12 +2646,12 @@ static bool handle_read_kdeth_eflags(struct hfi1_ctxtdata *rcd,
        u32 fpsn;
 
        lockdep_assert_held(&qp->r_lock);
+       spin_lock(&qp->s_lock);
        /* If the psn is out of valid range, drop the packet */
        if (cmp_psn(ibpsn, qp->s_last_psn) < 0 ||
            cmp_psn(ibpsn, qp->s_psn) > 0)
-               return ret;
+               goto s_unlock;
 
-       spin_lock(&qp->s_lock);
        /*
         * Note that NAKs implicitly ACK outstanding SEND and RDMA write
         * requests and implicitly NAK RDMA read and atomic requests issued
@@ -2740,9 +2699,12 @@ static bool handle_read_kdeth_eflags(struct hfi1_ctxtdata *rcd,
 
                wqe = do_rc_completion(qp, wqe, ibp);
                if (qp->s_acked == qp->s_tail)
-                       break;
+                       goto s_unlock;
        }
 
+       if (qp->s_acked == qp->s_tail)
+               goto s_unlock;
+
        /* Handle the eflags for the request */
        if (wqe->wr.opcode != IB_WR_TID_RDMA_READ)
                goto s_unlock;
@@ -2922,7 +2884,7 @@ bool hfi1_handle_kdeth_eflags(struct hfi1_ctxtdata *rcd,
                if (lnh == HFI1_LRH_GRH)
                        goto r_unlock;
 
-               if (tid_rdma_tid_err(rcd, packet, rcv_type, opcode))
+               if (tid_rdma_tid_err(packet, rcv_type))
                        goto r_unlock;
        }
 
@@ -2942,8 +2904,15 @@ bool hfi1_handle_kdeth_eflags(struct hfi1_ctxtdata *rcd,
         */
        spin_lock(&qp->s_lock);
        qpriv = qp->priv;
+       if (qpriv->r_tid_tail == HFI1_QP_WQE_INVALID ||
+           qpriv->r_tid_tail == qpriv->r_tid_head)
+               goto unlock;
        e = &qp->s_ack_queue[qpriv->r_tid_tail];
+       if (e->opcode != TID_OP(WRITE_REQ))
+               goto unlock;
        req = ack_to_tid_req(e);
+       if (req->comp_seg == req->cur_seg)
+               goto unlock;
        flow = &req->flows[req->clear_tail];
        trace_hfi1_eflags_err_write(qp, rcv_type, rte, psn);
        trace_hfi1_rsp_handle_kdeth_eflags(qp, psn);
@@ -4509,7 +4478,7 @@ void hfi1_rc_rcv_tid_rdma_ack(struct hfi1_packet *packet)
        struct rvt_swqe *wqe;
        struct tid_rdma_request *req;
        struct tid_rdma_flow *flow;
-       u32 aeth, psn, req_psn, ack_psn, resync_psn, ack_kpsn;
+       u32 aeth, psn, req_psn, ack_psn, flpsn, resync_psn, ack_kpsn;
        unsigned long flags;
        u16 fidx;
 
@@ -4538,6 +4507,9 @@ void hfi1_rc_rcv_tid_rdma_ack(struct hfi1_packet *packet)
                ack_kpsn--;
        }
 
+       if (unlikely(qp->s_acked == qp->s_tail))
+               goto ack_op_err;
+
        wqe = rvt_get_swqe_ptr(qp, qp->s_acked);
 
        if (wqe->wr.opcode != IB_WR_TID_RDMA_WRITE)
@@ -4550,7 +4522,8 @@ void hfi1_rc_rcv_tid_rdma_ack(struct hfi1_packet *packet)
        trace_hfi1_tid_flow_rcv_tid_ack(qp, req->acked_tail, flow);
 
        /* Drop stale ACK/NAK */
-       if (cmp_psn(psn, full_flow_psn(flow, flow->flow_state.spsn)) < 0)
+       if (cmp_psn(psn, full_flow_psn(flow, flow->flow_state.spsn)) < 0 ||
+           cmp_psn(req_psn, flow->flow_state.resp_ib_psn) < 0)
                goto ack_op_err;
 
        while (cmp_psn(ack_kpsn,
@@ -4712,7 +4685,12 @@ done:
                switch ((aeth >> IB_AETH_CREDIT_SHIFT) &
                        IB_AETH_CREDIT_MASK) {
                case 0: /* PSN sequence error */
+                       if (!req->flows)
+                               break;
                        flow = &req->flows[req->acked_tail];
+                       flpsn = full_flow_psn(flow, flow->flow_state.lpsn);
+                       if (cmp_psn(psn, flpsn) > 0)
+                               break;
                        trace_hfi1_tid_flow_rcv_tid_ack(qp, req->acked_tail,
                                                        flow);
                        req->r_ack_psn = mask_psn(be32_to_cpu(ohdr->bth[2]));
index 68c951491a08af9d34ed6c88410fc6a440f1c01b..57079110af9b5fb95fb1aaf4d13d8ae8aebc34e1 100644 (file)
@@ -1677,8 +1677,6 @@ tx_err:
                                    tx_buf_size, DMA_TO_DEVICE);
                kfree(tun_qp->tx_ring[i].buf.addr);
        }
-       kfree(tun_qp->tx_ring);
-       tun_qp->tx_ring = NULL;
        i = MLX4_NUM_TUNNEL_BUFS;
 err:
        while (i > 0) {
@@ -1687,6 +1685,8 @@ err:
                                    rx_buf_size, DMA_FROM_DEVICE);
                kfree(tun_qp->ring[i].addr);
        }
+       kfree(tun_qp->tx_ring);
+       tun_qp->tx_ring = NULL;
        kfree(tun_qp->ring);
        tun_qp->ring = NULL;
        return -ENOMEM;
index e12a4404096b6da2ec45f27104b49f6fd5ec4bf6..0569bcab02d4811d6d84ab986fa17c14b2e7a6da 100644 (file)
@@ -1023,7 +1023,7 @@ static int mlx5_ib_query_device(struct ib_device *ibdev,
        props->timestamp_mask = 0x7FFFFFFFFFFFFFFFULL;
 
        if (IS_ENABLED(CONFIG_INFINIBAND_ON_DEMAND_PAGING)) {
-               if (MLX5_CAP_GEN(mdev, pg))
+               if (dev->odp_caps.general_caps & IB_ODP_SUPPORT)
                        props->device_cap_flags |= IB_DEVICE_ON_DEMAND_PAGING;
                props->odp_caps = dev->odp_caps;
        }
@@ -6139,6 +6139,8 @@ static int mlx5_ib_stage_init_init(struct mlx5_ib_dev *dev)
                dev->port[i].roce.last_port_state = IB_PORT_DOWN;
        }
 
+       mlx5_ib_internal_fill_odp_caps(dev);
+
        err = mlx5_ib_init_multiport_master(dev);
        if (err)
                return err;
@@ -6563,8 +6565,6 @@ static void mlx5_ib_stage_dev_res_cleanup(struct mlx5_ib_dev *dev)
 
 static int mlx5_ib_stage_odp_init(struct mlx5_ib_dev *dev)
 {
-       mlx5_ib_internal_fill_odp_caps(dev);
-
        return mlx5_ib_odp_init_one(dev);
 }
 
index fe1a76d8531cee8b5d7e347c54fdbc1c51caaac3..a40e0abf233809c9c168b0a58d9e7f2b6c076614 100644 (file)
@@ -57,9 +57,10 @@ void mlx5_ib_cont_pages(struct ib_umem *umem, u64 addr,
        int entry;
 
        if (umem->is_odp) {
-               unsigned int page_shift = to_ib_umem_odp(umem)->page_shift;
+               struct ib_umem_odp *odp = to_ib_umem_odp(umem);
+               unsigned int page_shift = odp->page_shift;
 
-               *ncont = ib_umem_page_count(umem);
+               *ncont = ib_umem_odp_num_pages(odp);
                *count = *ncont << (page_shift - PAGE_SHIFT);
                *shift = page_shift;
                if (order)
index f6a53455bf8bd7050814c60c5d070e6aade844de..9ae587b74b121ddc637ad22b697a141e25cf3878 100644 (file)
@@ -1475,4 +1475,18 @@ int bfregn_to_uar_index(struct mlx5_ib_dev *dev,
                        bool dyn_bfreg);
 
 int mlx5_ib_qp_set_counter(struct ib_qp *qp, struct rdma_counter *counter);
+
+static inline bool mlx5_ib_can_use_umr(struct mlx5_ib_dev *dev,
+                                      bool do_modify_atomic)
+{
+       if (MLX5_CAP_GEN(dev->mdev, umr_modify_entity_size_disabled))
+               return false;
+
+       if (do_modify_atomic &&
+           MLX5_CAP_GEN(dev->mdev, atomic) &&
+           MLX5_CAP_GEN(dev->mdev, umr_modify_atomic_disabled))
+               return false;
+
+       return true;
+}
 #endif /* MLX5_IB_H */
index b74fad08412fb1388ceefcf3787e5660c3fd7d10..3401f5f6792e6bb79e472f6411eade5c2d1e2dab 100644 (file)
@@ -1293,9 +1293,7 @@ struct ib_mr *mlx5_ib_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
        if (err < 0)
                return ERR_PTR(err);
 
-       use_umr = !MLX5_CAP_GEN(dev->mdev, umr_modify_entity_size_disabled) &&
-                 (!MLX5_CAP_GEN(dev->mdev, umr_modify_atomic_disabled) ||
-                  !MLX5_CAP_GEN(dev->mdev, atomic));
+       use_umr = mlx5_ib_can_use_umr(dev, true);
 
        if (order <= mr_cache_max_order(dev) && use_umr) {
                mr = alloc_mr_from_cache(pd, umem, virt_addr, length, ncont,
@@ -1448,7 +1446,8 @@ int mlx5_ib_rereg_user_mr(struct ib_mr *ib_mr, int flags, u64 start,
                        goto err;
        }
 
-       if (flags & IB_MR_REREG_TRANS && !use_umr_mtt_update(mr, addr, len)) {
+       if (!mlx5_ib_can_use_umr(dev, true) ||
+           (flags & IB_MR_REREG_TRANS && !use_umr_mtt_update(mr, addr, len))) {
                /*
                 * UMR can't be used - MKey needs to be replaced.
                 */
index 1d257d1b3b0da0b1a1035a469100ab6d613b54f6..0a59912a4cef640067472319da83d7123f6eb5d1 100644 (file)
@@ -301,7 +301,8 @@ void mlx5_ib_internal_fill_odp_caps(struct mlx5_ib_dev *dev)
 
        memset(caps, 0, sizeof(*caps));
 
-       if (!MLX5_CAP_GEN(dev->mdev, pg))
+       if (!MLX5_CAP_GEN(dev->mdev, pg) ||
+           !mlx5_ib_can_use_umr(dev, true))
                return;
 
        caps->general_caps = IB_ODP_SUPPORT;
@@ -355,7 +356,8 @@ void mlx5_ib_internal_fill_odp_caps(struct mlx5_ib_dev *dev)
 
        if (MLX5_CAP_GEN(dev->mdev, fixed_buffer_size) &&
            MLX5_CAP_GEN(dev->mdev, null_mkey) &&
-           MLX5_CAP_GEN(dev->mdev, umr_extended_translation_offset))
+           MLX5_CAP_GEN(dev->mdev, umr_extended_translation_offset) &&
+           !MLX5_CAP_GEN(dev->mdev, umr_indirect_mkey_disabled))
                caps->general_caps |= IB_ODP_SUPPORT_IMPLICIT;
 
        return;
@@ -1622,8 +1624,10 @@ int mlx5_ib_odp_init_one(struct mlx5_ib_dev *dev)
 {
        int ret = 0;
 
-       if (dev->odp_caps.general_caps & IB_ODP_SUPPORT)
-               ib_set_device_ops(&dev->ib_dev, &mlx5_ib_dev_odp_ops);
+       if (!(dev->odp_caps.general_caps & IB_ODP_SUPPORT))
+               return ret;
+
+       ib_set_device_ops(&dev->ib_dev, &mlx5_ib_dev_odp_ops);
 
        if (dev->odp_caps.general_caps & IB_ODP_SUPPORT_IMPLICIT) {
                ret = mlx5_cmd_null_mkey(dev->mdev, &dev->null_mkey);
@@ -1633,9 +1637,6 @@ int mlx5_ib_odp_init_one(struct mlx5_ib_dev *dev)
                }
        }
 
-       if (!MLX5_CAP_GEN(dev->mdev, pg))
-               return ret;
-
        ret = mlx5_ib_create_pf_eq(dev, &dev->odp_pf_eq);
 
        return ret;
@@ -1643,7 +1644,7 @@ int mlx5_ib_odp_init_one(struct mlx5_ib_dev *dev)
 
 void mlx5_ib_odp_cleanup_one(struct mlx5_ib_dev *dev)
 {
-       if (!MLX5_CAP_GEN(dev->mdev, pg))
+       if (!(dev->odp_caps.general_caps & IB_ODP_SUPPORT))
                return;
 
        mlx5_ib_destroy_pf_eq(dev, &dev->odp_pf_eq);
index 379328b2598fd59f1de6674df0918f4d6d79a91c..72869ff4a33420d05a5d7265e0870abb6234fbec 100644 (file)
@@ -4162,7 +4162,7 @@ static u64 get_xlt_octo(u64 bytes)
               MLX5_IB_UMR_OCTOWORD;
 }
 
-static __be64 frwr_mkey_mask(void)
+static __be64 frwr_mkey_mask(bool atomic)
 {
        u64 result;
 
@@ -4175,10 +4175,12 @@ static __be64 frwr_mkey_mask(void)
                MLX5_MKEY_MASK_LW               |
                MLX5_MKEY_MASK_RR               |
                MLX5_MKEY_MASK_RW               |
-               MLX5_MKEY_MASK_A                |
                MLX5_MKEY_MASK_SMALL_FENCE      |
                MLX5_MKEY_MASK_FREE;
 
+       if (atomic)
+               result |= MLX5_MKEY_MASK_A;
+
        return cpu_to_be64(result);
 }
 
@@ -4204,7 +4206,7 @@ static __be64 sig_mkey_mask(void)
 }
 
 static void set_reg_umr_seg(struct mlx5_wqe_umr_ctrl_seg *umr,
-                           struct mlx5_ib_mr *mr, u8 flags)
+                           struct mlx5_ib_mr *mr, u8 flags, bool atomic)
 {
        int size = (mr->ndescs + mr->meta_ndescs) * mr->desc_size;
 
@@ -4212,7 +4214,7 @@ static void set_reg_umr_seg(struct mlx5_wqe_umr_ctrl_seg *umr,
 
        umr->flags = flags;
        umr->xlt_octowords = cpu_to_be16(get_xlt_octo(size));
-       umr->mkey_mask = frwr_mkey_mask();
+       umr->mkey_mask = frwr_mkey_mask(atomic);
 }
 
 static void set_linv_umr_seg(struct mlx5_wqe_umr_ctrl_seg *umr)
@@ -4811,10 +4813,22 @@ static int set_reg_wr(struct mlx5_ib_qp *qp,
 {
        struct mlx5_ib_mr *mr = to_mmr(wr->mr);
        struct mlx5_ib_pd *pd = to_mpd(qp->ibqp.pd);
+       struct mlx5_ib_dev *dev = to_mdev(pd->ibpd.device);
        int mr_list_size = (mr->ndescs + mr->meta_ndescs) * mr->desc_size;
        bool umr_inline = mr_list_size <= MLX5_IB_SQ_UMR_INLINE_THRESHOLD;
+       bool atomic = wr->access & IB_ACCESS_REMOTE_ATOMIC;
        u8 flags = 0;
 
+       if (!mlx5_ib_can_use_umr(dev, atomic)) {
+               mlx5_ib_warn(to_mdev(qp->ibqp.device),
+                            "Fast update of %s for MR is disabled\n",
+                            (MLX5_CAP_GEN(dev->mdev,
+                                          umr_modify_entity_size_disabled)) ?
+                                    "entity size" :
+                                    "atomic access");
+               return -EINVAL;
+       }
+
        if (unlikely(wr->wr.send_flags & IB_SEND_INLINE)) {
                mlx5_ib_warn(to_mdev(qp->ibqp.device),
                             "Invalid IB_SEND_INLINE send flag\n");
@@ -4826,7 +4840,7 @@ static int set_reg_wr(struct mlx5_ib_qp *qp,
        if (umr_inline)
                flags |= MLX5_UMR_INLINE;
 
-       set_reg_umr_seg(*seg, mr, flags);
+       set_reg_umr_seg(*seg, mr, flags, atomic);
        *seg += sizeof(struct mlx5_wqe_umr_ctrl_seg);
        *size += sizeof(struct mlx5_wqe_umr_ctrl_seg) / 16;
        handle_post_send_edge(&qp->sq, seg, *size, cur_edge);
index 77b1aabf6ff357245ea7b3c3b04ee570320eb9b1..dba4535494abdc28a5317e1b96ea3cb3b8e7a852 100644 (file)
@@ -138,9 +138,9 @@ struct siw_umem {
 };
 
 struct siw_pble {
-       u64 addr; /* Address of assigned user buffer */
-       u64 size; /* Size of this entry */
-       u64 pbl_off; /* Total offset from start of PBL */
+       dma_addr_t addr; /* Address of assigned buffer */
+       unsigned int size; /* Size of this entry */
+       unsigned long pbl_off; /* Total offset from start of PBL */
 };
 
 struct siw_pbl {
@@ -734,7 +734,7 @@ static inline void siw_crc_skb(struct siw_rx_stream *srx, unsigned int len)
                  "MEM[0x%08x] %s: " fmt, mem->stag, __func__, ##__VA_ARGS__)
 
 #define siw_dbg_cep(cep, fmt, ...)                                             \
-       ibdev_dbg(&cep->sdev->base_dev, "CEP[0x%p] %s: " fmt,                  \
+       ibdev_dbg(&cep->sdev->base_dev, "CEP[0x%pK] %s: " fmt,                  \
                  cep, __func__, ##__VA_ARGS__)
 
 void siw_cq_flush(struct siw_cq *cq);
index 9ce8a1b925d26306f18038c613c69ef09f5983bc..1db5ad3d9580ee00a4c8ee65da2769146bcf731b 100644 (file)
@@ -355,8 +355,8 @@ static int siw_cm_upcall(struct siw_cep *cep, enum iw_cm_event_type reason,
                getname_local(cep->sock, &event.local_addr);
                getname_peer(cep->sock, &event.remote_addr);
        }
-       siw_dbg_cep(cep, "[QP %u]: id 0x%p, reason=%d, status=%d\n",
-                   cep->qp ? qp_id(cep->qp) : -1, id, reason, status);
+       siw_dbg_cep(cep, "[QP %u]: reason=%d, status=%d\n",
+                   cep->qp ? qp_id(cep->qp) : UINT_MAX, reason, status);
 
        return id->event_handler(id, &event);
 }
@@ -947,8 +947,6 @@ static void siw_accept_newconn(struct siw_cep *cep)
        siw_cep_get(new_cep);
        new_s->sk->sk_user_data = new_cep;
 
-       siw_dbg_cep(cep, "listen socket 0x%p, new 0x%p\n", s, new_s);
-
        if (siw_tcp_nagle == false) {
                int val = 1;
 
@@ -1011,7 +1009,8 @@ static void siw_cm_work_handler(struct work_struct *w)
        cep = work->cep;
 
        siw_dbg_cep(cep, "[QP %u]: work type: %d, state %d\n",
-                   cep->qp ? qp_id(cep->qp) : -1, work->type, cep->state);
+                   cep->qp ? qp_id(cep->qp) : UINT_MAX,
+                   work->type, cep->state);
 
        siw_cep_set_inuse(cep);
 
@@ -1145,9 +1144,9 @@ static void siw_cm_work_handler(struct work_struct *w)
        }
        if (release_cep) {
                siw_dbg_cep(cep,
-                           "release: timer=%s, QP[%u], id 0x%p\n",
+                           "release: timer=%s, QP[%u]\n",
                            cep->mpa_timer ? "y" : "n",
-                           cep->qp ? qp_id(cep->qp) : -1, cep->cm_id);
+                           cep->qp ? qp_id(cep->qp) : UINT_MAX);
 
                siw_cancel_mpatimer(cep);
 
@@ -1211,8 +1210,8 @@ int siw_cm_queue_work(struct siw_cep *cep, enum siw_work_type type)
                else
                        delay = MPAREP_TIMEOUT;
        }
-       siw_dbg_cep(cep, "[QP %u]: work type: %d, work 0x%p, timeout %lu\n",
-                   cep->qp ? qp_id(cep->qp) : -1, type, work, delay);
+       siw_dbg_cep(cep, "[QP %u]: work type: %d, timeout %lu\n",
+                   cep->qp ? qp_id(cep->qp) : -1, type, delay);
 
        queue_delayed_work(siw_cm_wq, &work->work, delay);
 
@@ -1376,16 +1375,16 @@ int siw_connect(struct iw_cm_id *id, struct iw_cm_conn_param *params)
        }
        if (v4)
                siw_dbg_qp(qp,
-                          "id 0x%p, pd_len %d, laddr %pI4 %d, raddr %pI4 %d\n",
-                          id, pd_len,
+                          "pd_len %d, laddr %pI4 %d, raddr %pI4 %d\n",
+                          pd_len,
                           &((struct sockaddr_in *)(laddr))->sin_addr,
                           ntohs(((struct sockaddr_in *)(laddr))->sin_port),
                           &((struct sockaddr_in *)(raddr))->sin_addr,
                           ntohs(((struct sockaddr_in *)(raddr))->sin_port));
        else
                siw_dbg_qp(qp,
-                          "id 0x%p, pd_len %d, laddr %pI6 %d, raddr %pI6 %d\n",
-                          id, pd_len,
+                          "pd_len %d, laddr %pI6 %d, raddr %pI6 %d\n",
+                          pd_len,
                           &((struct sockaddr_in6 *)(laddr))->sin6_addr,
                           ntohs(((struct sockaddr_in6 *)(laddr))->sin6_port),
                           &((struct sockaddr_in6 *)(raddr))->sin6_addr,
@@ -1508,14 +1507,13 @@ int siw_connect(struct iw_cm_id *id, struct iw_cm_conn_param *params)
        if (rv >= 0) {
                rv = siw_cm_queue_work(cep, SIW_CM_WORK_MPATIMEOUT);
                if (!rv) {
-                       siw_dbg_cep(cep, "id 0x%p, [QP %u]: exit\n", id,
-                                   qp_id(qp));
+                       siw_dbg_cep(cep, "[QP %u]: exit\n", qp_id(qp));
                        siw_cep_set_free(cep);
                        return 0;
                }
        }
 error:
-       siw_dbg_qp(qp, "failed: %d\n", rv);
+       siw_dbg(id->device, "failed: %d\n", rv);
 
        if (cep) {
                siw_socket_disassoc(s);
@@ -1540,7 +1538,8 @@ error:
        } else if (s) {
                sock_release(s);
        }
-       siw_qp_put(qp);
+       if (qp)
+               siw_qp_put(qp);
 
        return rv;
 }
@@ -1580,7 +1579,7 @@ int siw_accept(struct iw_cm_id *id, struct iw_cm_conn_param *params)
        siw_cancel_mpatimer(cep);
 
        if (cep->state != SIW_EPSTATE_RECVD_MPAREQ) {
-               siw_dbg_cep(cep, "id 0x%p: out of state\n", id);
+               siw_dbg_cep(cep, "out of state\n");
 
                siw_cep_set_free(cep);
                siw_cep_put(cep);
@@ -1601,7 +1600,7 @@ int siw_accept(struct iw_cm_id *id, struct iw_cm_conn_param *params)
                up_write(&qp->state_lock);
                goto error;
        }
-       siw_dbg_cep(cep, "id 0x%p\n", id);
+       siw_dbg_cep(cep, "[QP %d]\n", params->qpn);
 
        if (try_gso && cep->mpa.hdr.params.bits & MPA_RR_FLAG_GSO_EXP) {
                siw_dbg_cep(cep, "peer allows GSO on TX\n");
@@ -1611,8 +1610,8 @@ int siw_accept(struct iw_cm_id *id, struct iw_cm_conn_param *params)
            params->ird > sdev->attrs.max_ird) {
                siw_dbg_cep(
                        cep,
-                       "id 0x%p, [QP %u]: ord %d (max %d), ird %d (max %d)\n",
-                       id, qp_id(qp), params->ord, sdev->attrs.max_ord,
+                       "[QP %u]: ord %d (max %d), ird %d (max %d)\n",
+                       qp_id(qp), params->ord, sdev->attrs.max_ord,
                        params->ird, sdev->attrs.max_ird);
                rv = -EINVAL;
                up_write(&qp->state_lock);
@@ -1624,8 +1623,8 @@ int siw_accept(struct iw_cm_id *id, struct iw_cm_conn_param *params)
        if (params->private_data_len > max_priv_data) {
                siw_dbg_cep(
                        cep,
-                       "id 0x%p, [QP %u]: private data length: %d (max %d)\n",
-                       id, qp_id(qp), params->private_data_len, max_priv_data);
+                       "[QP %u]: private data length: %d (max %d)\n",
+                       qp_id(qp), params->private_data_len, max_priv_data);
                rv = -EINVAL;
                up_write(&qp->state_lock);
                goto error;
@@ -1679,7 +1678,7 @@ int siw_accept(struct iw_cm_id *id, struct iw_cm_conn_param *params)
                qp_attrs.flags = SIW_MPA_CRC;
        qp_attrs.state = SIW_QP_STATE_RTS;
 
-       siw_dbg_cep(cep, "id 0x%p, [QP%u]: moving to rts\n", id, qp_id(qp));
+       siw_dbg_cep(cep, "[QP%u]: moving to rts\n", qp_id(qp));
 
        /* Associate QP with CEP */
        siw_cep_get(cep);
@@ -1700,8 +1699,8 @@ int siw_accept(struct iw_cm_id *id, struct iw_cm_conn_param *params)
        if (rv)
                goto error;
 
-       siw_dbg_cep(cep, "id 0x%p, [QP %u]: send mpa reply, %d byte pdata\n",
-                   id, qp_id(qp), params->private_data_len);
+       siw_dbg_cep(cep, "[QP %u]: send mpa reply, %d byte pdata\n",
+                   qp_id(qp), params->private_data_len);
 
        rv = siw_send_mpareqrep(cep, params->private_data,
                                params->private_data_len);
@@ -1759,14 +1758,14 @@ int siw_reject(struct iw_cm_id *id, const void *pdata, u8 pd_len)
        siw_cancel_mpatimer(cep);
 
        if (cep->state != SIW_EPSTATE_RECVD_MPAREQ) {
-               siw_dbg_cep(cep, "id 0x%p: out of state\n", id);
+               siw_dbg_cep(cep, "out of state\n");
 
                siw_cep_set_free(cep);
                siw_cep_put(cep); /* put last reference */
 
                return -ECONNRESET;
        }
-       siw_dbg_cep(cep, "id 0x%p, cep->state %d, pd_len %d\n", id, cep->state,
+       siw_dbg_cep(cep, "cep->state %d, pd_len %d\n", cep->state,
                    pd_len);
 
        if (__mpa_rr_revision(cep->mpa.hdr.params.bits) >= MPA_REVISION_1) {
@@ -1804,14 +1803,14 @@ static int siw_listen_address(struct iw_cm_id *id, int backlog,
        rv = kernel_setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&s_val,
                               sizeof(s_val));
        if (rv) {
-               siw_dbg(id->device, "id 0x%p: setsockopt error: %d\n", id, rv);
+               siw_dbg(id->device, "setsockopt error: %d\n", rv);
                goto error;
        }
        rv = s->ops->bind(s, laddr, addr_family == AF_INET ?
                                    sizeof(struct sockaddr_in) :
                                    sizeof(struct sockaddr_in6));
        if (rv) {
-               siw_dbg(id->device, "id 0x%p: socket bind error: %d\n", id, rv);
+               siw_dbg(id->device, "socket bind error: %d\n", rv);
                goto error;
        }
        cep = siw_cep_alloc(sdev);
@@ -1824,13 +1823,13 @@ static int siw_listen_address(struct iw_cm_id *id, int backlog,
        rv = siw_cm_alloc_work(cep, backlog);
        if (rv) {
                siw_dbg(id->device,
-                       "id 0x%p: alloc_work error %d, backlog %d\n", id,
+                       "alloc_work error %d, backlog %d\n",
                        rv, backlog);
                goto error;
        }
        rv = s->ops->listen(s, backlog);
        if (rv) {
-               siw_dbg(id->device, "id 0x%p: listen error %d\n", id, rv);
+               siw_dbg(id->device, "listen error %d\n", rv);
                goto error;
        }
        cep->cm_id = id;
@@ -1914,8 +1913,7 @@ static void siw_drop_listeners(struct iw_cm_id *id)
 
                list_del(p);
 
-               siw_dbg_cep(cep, "id 0x%p: drop cep, state %d\n", id,
-                           cep->state);
+               siw_dbg_cep(cep, "drop cep, state %d\n", cep->state);
 
                siw_cep_set_inuse(cep);
 
@@ -1952,7 +1950,7 @@ int siw_create_listen(struct iw_cm_id *id, int backlog)
        struct net_device *dev = to_siw_dev(id->device)->netdev;
        int rv = 0, listeners = 0;
 
-       siw_dbg(id->device, "id 0x%p: backlog %d\n", id, backlog);
+       siw_dbg(id->device, "backlog %d\n", backlog);
 
        /*
         * For each attached address of the interface, create a
@@ -1968,8 +1966,8 @@ int siw_create_listen(struct iw_cm_id *id, int backlog)
                s_raddr = (struct sockaddr_in *)&id->remote_addr;
 
                siw_dbg(id->device,
-                       "id 0x%p: laddr %pI4:%d, raddr %pI4:%d\n",
-                       id, &s_laddr.sin_addr, ntohs(s_laddr.sin_port),
+                       "laddr %pI4:%d, raddr %pI4:%d\n",
+                       &s_laddr.sin_addr, ntohs(s_laddr.sin_port),
                        &s_raddr->sin_addr, ntohs(s_raddr->sin_port));
 
                rtnl_lock();
@@ -1994,8 +1992,8 @@ int siw_create_listen(struct iw_cm_id *id, int backlog)
                        *s_raddr = &to_sockaddr_in6(id->remote_addr);
 
                siw_dbg(id->device,
-                       "id 0x%p: laddr %pI6:%d, raddr %pI6:%d\n",
-                       id, &s_laddr->sin6_addr, ntohs(s_laddr->sin6_port),
+                       "laddr %pI6:%d, raddr %pI6:%d\n",
+                       &s_laddr->sin6_addr, ntohs(s_laddr->sin6_port),
                        &s_raddr->sin6_addr, ntohs(s_raddr->sin6_port));
 
                read_lock_bh(&in6_dev->lock);
@@ -2028,17 +2026,15 @@ int siw_create_listen(struct iw_cm_id *id, int backlog)
        else if (!rv)
                rv = -EINVAL;
 
-       siw_dbg(id->device, "id 0x%p: %s\n", id, rv ? "FAIL" : "OK");
+       siw_dbg(id->device, "%s\n", rv ? "FAIL" : "OK");
 
        return rv;
 }
 
 int siw_destroy_listen(struct iw_cm_id *id)
 {
-       siw_dbg(id->device, "id 0x%p\n", id);
-
        if (!id->provider_data) {
-               siw_dbg(id->device, "id 0x%p: no cep(s)\n", id);
+               siw_dbg(id->device, "no cep(s)\n");
                return 0;
        }
        siw_drop_listeners(id);
index e381ae9b7d62498ed6b8ab8a9a4d04ea2f1f92eb..d8db3bee9da7f5015d133cfeef29af5e9e3cef42 100644 (file)
@@ -71,9 +71,10 @@ int siw_reap_cqe(struct siw_cq *cq, struct ib_wc *wc)
                                wc->wc_flags = IB_WC_WITH_INVALIDATE;
                        }
                        wc->qp = cqe->base_qp;
-                       siw_dbg_cq(cq, "idx %u, type %d, flags %2x, id 0x%p\n",
+                       siw_dbg_cq(cq,
+                                  "idx %u, type %d, flags %2x, id 0x%pK\n",
                                   cq->cq_get % cq->num_cqe, cqe->opcode,
-                                  cqe->flags, (void *)cqe->id);
+                                  cqe->flags, (void *)(uintptr_t)cqe->id);
                }
                WRITE_ONCE(cqe->flags, 0);
                cq->cq_get++;
index 67171c82b0c4f98ba7a8dbca4b5bb70ed8080115..87a56039f0ef11192fe3c73e6aaef19b660f417e 100644 (file)
@@ -197,12 +197,12 @@ int siw_check_mem(struct ib_pd *pd, struct siw_mem *mem, u64 addr,
         */
        if (addr < mem->va || addr + len > mem->va + mem->len) {
                siw_dbg_pd(pd, "MEM interval len %d\n", len);
-               siw_dbg_pd(pd, "[0x%016llx, 0x%016llx] out of bounds\n",
-                          (unsigned long long)addr,
-                          (unsigned long long)(addr + len));
-               siw_dbg_pd(pd, "[0x%016llx, 0x%016llx] STag=0x%08x\n",
-                          (unsigned long long)mem->va,
-                          (unsigned long long)(mem->va + mem->len),
+               siw_dbg_pd(pd, "[0x%pK, 0x%pK] out of bounds\n",
+                          (void *)(uintptr_t)addr,
+                          (void *)(uintptr_t)(addr + len));
+               siw_dbg_pd(pd, "[0x%pK, 0x%pK] STag=0x%08x\n",
+                          (void *)(uintptr_t)mem->va,
+                          (void *)(uintptr_t)(mem->va + mem->len),
                           mem->stag);
 
                return -E_BASE_BOUNDS;
@@ -330,7 +330,7 @@ out:
  * Optionally, provides remaining len within current element, and
  * current PBL index for later resume at same element.
  */
-u64 siw_pbl_get_buffer(struct siw_pbl *pbl, u64 off, int *len, int *idx)
+dma_addr_t siw_pbl_get_buffer(struct siw_pbl *pbl, u64 off, int *len, int *idx)
 {
        int i = idx ? *idx : 0;
 
index f43daf28089122ccc515c6ffae0ba73745a5e07d..db138c8423da547bd35e8737dfa15b04cfaa7c62 100644 (file)
@@ -9,7 +9,7 @@
 struct siw_umem *siw_umem_get(u64 start, u64 len, bool writable);
 void siw_umem_release(struct siw_umem *umem, bool dirty);
 struct siw_pbl *siw_pbl_alloc(u32 num_buf);
-u64 siw_pbl_get_buffer(struct siw_pbl *pbl, u64 off, int *len, int *idx);
+dma_addr_t siw_pbl_get_buffer(struct siw_pbl *pbl, u64 off, int *len, int *idx);
 struct siw_mem *siw_mem_id2obj(struct siw_device *sdev, int stag_index);
 int siw_mem_add(struct siw_device *sdev, struct siw_mem *m);
 int siw_invalidate_stag(struct ib_pd *pd, u32 stag);
index 0990307c5d2cde951d646b2d06e990670f44a709..430314c8abd948c200d0eb1c203d5325c8230be1 100644 (file)
@@ -949,7 +949,7 @@ skip_irq:
                                rv = -EINVAL;
                                goto out;
                        }
-                       wqe->sqe.sge[0].laddr = (u64)&wqe->sqe.sge[1];
+                       wqe->sqe.sge[0].laddr = (uintptr_t)&wqe->sqe.sge[1];
                        wqe->sqe.sge[0].lkey = 0;
                        wqe->sqe.num_sge = 1;
                }
index f87657a11657223ee06f22b6bac91833fb7ab57b..c0a887240325854bb9af0de94d2e86ff6c9e0f4f 100644 (file)
@@ -38,9 +38,10 @@ static int siw_rx_umem(struct siw_rx_stream *srx, struct siw_umem *umem,
 
                p = siw_get_upage(umem, dest_addr);
                if (unlikely(!p)) {
-                       pr_warn("siw: %s: [QP %u]: bogus addr: %p, %p\n",
+                       pr_warn("siw: %s: [QP %u]: bogus addr: %pK, %pK\n",
                                __func__, qp_id(rx_qp(srx)),
-                               (void *)dest_addr, (void *)umem->fp_addr);
+                               (void *)(uintptr_t)dest_addr,
+                               (void *)(uintptr_t)umem->fp_addr);
                        /* siw internal error */
                        srx->skb_copied += copied;
                        srx->skb_new -= copied;
@@ -50,7 +51,7 @@ static int siw_rx_umem(struct siw_rx_stream *srx, struct siw_umem *umem,
                pg_off = dest_addr & ~PAGE_MASK;
                bytes = min(len, (int)PAGE_SIZE - pg_off);
 
-               siw_dbg_qp(rx_qp(srx), "page %p, bytes=%u\n", p, bytes);
+               siw_dbg_qp(rx_qp(srx), "page %pK, bytes=%u\n", p, bytes);
 
                dest = kmap_atomic(p);
                rv = skb_copy_bits(srx->skb, srx->skb_offset, dest + pg_off,
@@ -104,11 +105,11 @@ static int siw_rx_kva(struct siw_rx_stream *srx, void *kva, int len)
 {
        int rv;
 
-       siw_dbg_qp(rx_qp(srx), "kva: 0x%p, len: %u\n", kva, len);
+       siw_dbg_qp(rx_qp(srx), "kva: 0x%pK, len: %u\n", kva, len);
 
        rv = skb_copy_bits(srx->skb, srx->skb_offset, kva, len);
        if (unlikely(rv)) {
-               pr_warn("siw: [QP %u]: %s, len %d, kva 0x%p, rv %d\n",
+               pr_warn("siw: [QP %u]: %s, len %d, kva 0x%pK, rv %d\n",
                        qp_id(rx_qp(srx)), __func__, len, kva, rv);
 
                return rv;
@@ -132,7 +133,7 @@ static int siw_rx_pbl(struct siw_rx_stream *srx, int *pbl_idx,
 
        while (len) {
                int bytes;
-               u64 buf_addr =
+               dma_addr_t buf_addr =
                        siw_pbl_get_buffer(pbl, offset, &bytes, pbl_idx);
                if (!buf_addr)
                        break;
@@ -485,8 +486,8 @@ int siw_proc_send(struct siw_qp *qp)
                mem_p = *mem;
                if (mem_p->mem_obj == NULL)
                        rv = siw_rx_kva(srx,
-                                       (void *)(sge->laddr + frx->sge_off),
-                                       sge_bytes);
+                               (void *)(uintptr_t)(sge->laddr + frx->sge_off),
+                               sge_bytes);
                else if (!mem_p->is_pbl)
                        rv = siw_rx_umem(srx, mem_p->umem,
                                         sge->laddr + frx->sge_off, sge_bytes);
@@ -598,8 +599,8 @@ int siw_proc_write(struct siw_qp *qp)
 
        if (mem->mem_obj == NULL)
                rv = siw_rx_kva(srx,
-                               (void *)(srx->ddp_to + srx->fpdu_part_rcvd),
-                               bytes);
+                       (void *)(uintptr_t)(srx->ddp_to + srx->fpdu_part_rcvd),
+                       bytes);
        else if (!mem->is_pbl)
                rv = siw_rx_umem(srx, mem->umem,
                                 srx->ddp_to + srx->fpdu_part_rcvd, bytes);
@@ -841,8 +842,9 @@ int siw_proc_rresp(struct siw_qp *qp)
        bytes = min(srx->fpdu_part_rem, srx->skb_new);
 
        if (mem_p->mem_obj == NULL)
-               rv = siw_rx_kva(srx, (void *)(sge->laddr + wqe->processed),
-                               bytes);
+               rv = siw_rx_kva(srx,
+                       (void *)(uintptr_t)(sge->laddr + wqe->processed),
+                       bytes);
        else if (!mem_p->is_pbl)
                rv = siw_rx_umem(srx, mem_p->umem, sge->laddr + wqe->processed,
                                 bytes);
index 43020d2040fc3394ce3ee18e0369986693f58b26..438a2917a47c20e3cb5b1cdb130632fd045c42c1 100644 (file)
@@ -26,7 +26,7 @@ static struct page *siw_get_pblpage(struct siw_mem *mem, u64 addr, int *idx)
 {
        struct siw_pbl *pbl = mem->pbl;
        u64 offset = addr - mem->va;
-       u64 paddr = siw_pbl_get_buffer(pbl, offset, NULL, idx);
+       dma_addr_t paddr = siw_pbl_get_buffer(pbl, offset, NULL, idx);
 
        if (paddr)
                return virt_to_page(paddr);
@@ -37,7 +37,7 @@ static struct page *siw_get_pblpage(struct siw_mem *mem, u64 addr, int *idx)
 /*
  * Copy short payload at provided destination payload address
  */
-static int siw_try_1seg(struct siw_iwarp_tx *c_tx, u64 paddr)
+static int siw_try_1seg(struct siw_iwarp_tx *c_tx, void *paddr)
 {
        struct siw_wqe *wqe = &c_tx->wqe_active;
        struct siw_sge *sge = &wqe->sqe.sge[0];
@@ -50,16 +50,16 @@ static int siw_try_1seg(struct siw_iwarp_tx *c_tx, u64 paddr)
                return 0;
 
        if (tx_flags(wqe) & SIW_WQE_INLINE) {
-               memcpy((void *)paddr, &wqe->sqe.sge[1], bytes);
+               memcpy(paddr, &wqe->sqe.sge[1], bytes);
        } else {
                struct siw_mem *mem = wqe->mem[0];
 
                if (!mem->mem_obj) {
                        /* Kernel client using kva */
-                       memcpy((void *)paddr, (void *)sge->laddr, bytes);
+                       memcpy(paddr,
+                              (const void *)(uintptr_t)sge->laddr, bytes);
                } else if (c_tx->in_syscall) {
-                       if (copy_from_user((void *)paddr,
-                                          (const void __user *)sge->laddr,
+                       if (copy_from_user(paddr, u64_to_user_ptr(sge->laddr),
                                           bytes))
                                return -EFAULT;
                } else {
@@ -79,12 +79,12 @@ static int siw_try_1seg(struct siw_iwarp_tx *c_tx, u64 paddr)
                        buffer = kmap_atomic(p);
 
                        if (likely(PAGE_SIZE - off >= bytes)) {
-                               memcpy((void *)paddr, buffer + off, bytes);
+                               memcpy(paddr, buffer + off, bytes);
                                kunmap_atomic(buffer);
                        } else {
                                unsigned long part = bytes - (PAGE_SIZE - off);
 
-                               memcpy((void *)paddr, buffer + off, part);
+                               memcpy(paddr, buffer + off, part);
                                kunmap_atomic(buffer);
 
                                if (!mem->is_pbl)
@@ -98,7 +98,7 @@ static int siw_try_1seg(struct siw_iwarp_tx *c_tx, u64 paddr)
                                        return -EFAULT;
 
                                buffer = kmap_atomic(p);
-                               memcpy((void *)(paddr + part), buffer,
+                               memcpy(paddr + part, buffer,
                                       bytes - part);
                                kunmap_atomic(buffer);
                        }
@@ -166,7 +166,7 @@ static int siw_qp_prepare_tx(struct siw_iwarp_tx *c_tx)
                c_tx->ctrl_len = sizeof(struct iwarp_send);
 
                crc = (char *)&c_tx->pkt.send_pkt.crc;
-               data = siw_try_1seg(c_tx, (u64)crc);
+               data = siw_try_1seg(c_tx, crc);
                break;
 
        case SIW_OP_SEND_REMOTE_INV:
@@ -189,7 +189,7 @@ static int siw_qp_prepare_tx(struct siw_iwarp_tx *c_tx)
                c_tx->ctrl_len = sizeof(struct iwarp_send_inv);
 
                crc = (char *)&c_tx->pkt.send_pkt.crc;
-               data = siw_try_1seg(c_tx, (u64)crc);
+               data = siw_try_1seg(c_tx, crc);
                break;
 
        case SIW_OP_WRITE:
@@ -201,7 +201,7 @@ static int siw_qp_prepare_tx(struct siw_iwarp_tx *c_tx)
                c_tx->ctrl_len = sizeof(struct iwarp_rdma_write);
 
                crc = (char *)&c_tx->pkt.write_pkt.crc;
-               data = siw_try_1seg(c_tx, (u64)crc);
+               data = siw_try_1seg(c_tx, crc);
                break;
 
        case SIW_OP_READ_RESPONSE:
@@ -216,7 +216,7 @@ static int siw_qp_prepare_tx(struct siw_iwarp_tx *c_tx)
                c_tx->ctrl_len = sizeof(struct iwarp_rdma_rresp);
 
                crc = (char *)&c_tx->pkt.write_pkt.crc;
-               data = siw_try_1seg(c_tx, (u64)crc);
+               data = siw_try_1seg(c_tx, crc);
                break;
 
        default:
@@ -398,15 +398,13 @@ static int siw_0copy_tx(struct socket *s, struct page **page,
 
 #define MAX_TRAILER (MPA_CRC_SIZE + 4)
 
-static void siw_unmap_pages(struct page **pages, int hdr_len, int num_maps)
+static void siw_unmap_pages(struct page **pp, unsigned long kmap_mask)
 {
-       if (hdr_len) {
-               ++pages;
-               --num_maps;
-       }
-       while (num_maps-- > 0) {
-               kunmap(*pages);
-               pages++;
+       while (kmap_mask) {
+               if (kmap_mask & BIT(0))
+                       kunmap(*pp);
+               pp++;
+               kmap_mask >>= 1;
        }
 }
 
@@ -437,6 +435,7 @@ static int siw_tx_hdt(struct siw_iwarp_tx *c_tx, struct socket *s)
        unsigned int data_len = c_tx->bytes_unsent, hdr_len = 0, trl_len = 0,
                     sge_off = c_tx->sge_off, sge_idx = c_tx->sge_idx,
                     pbl_idx = c_tx->pbl_idx;
+       unsigned long kmap_mask = 0L;
 
        if (c_tx->state == SIW_SEND_HDR) {
                if (c_tx->use_sendpage) {
@@ -463,8 +462,7 @@ static int siw_tx_hdt(struct siw_iwarp_tx *c_tx, struct socket *s)
 
                if (!(tx_flags(wqe) & SIW_WQE_INLINE)) {
                        mem = wqe->mem[sge_idx];
-                       if (!mem->mem_obj)
-                               is_kva = 1;
+                       is_kva = mem->mem_obj == NULL ? 1 : 0;
                } else {
                        is_kva = 1;
                }
@@ -473,7 +471,8 @@ static int siw_tx_hdt(struct siw_iwarp_tx *c_tx, struct socket *s)
                         * tx from kernel virtual address: either inline data
                         * or memory region with assigned kernel buffer
                         */
-                       iov[seg].iov_base = (void *)(sge->laddr + sge_off);
+                       iov[seg].iov_base =
+                               (void *)(uintptr_t)(sge->laddr + sge_off);
                        iov[seg].iov_len = sge_len;
 
                        if (do_crc)
@@ -500,12 +499,7 @@ static int siw_tx_hdt(struct siw_iwarp_tx *c_tx, struct socket *s)
                                        p = siw_get_upage(mem->umem,
                                                          sge->laddr + sge_off);
                                if (unlikely(!p)) {
-                                       if (hdr_len)
-                                               seg--;
-                                       if (!c_tx->use_sendpage && seg) {
-                                               siw_unmap_pages(page_array,
-                                                               hdr_len, seg);
-                                       }
+                                       siw_unmap_pages(page_array, kmap_mask);
                                        wqe->processed -= c_tx->bytes_unsent;
                                        rv = -EFAULT;
                                        goto done_crc;
@@ -515,6 +509,10 @@ static int siw_tx_hdt(struct siw_iwarp_tx *c_tx, struct socket *s)
                                if (!c_tx->use_sendpage) {
                                        iov[seg].iov_base = kmap(p) + fp_off;
                                        iov[seg].iov_len = plen;
+
+                                       /* Remember for later kunmap() */
+                                       kmap_mask |= BIT(seg);
+
                                        if (do_crc)
                                                crypto_shash_update(
                                                        c_tx->mpa_crc_hd,
@@ -526,13 +524,13 @@ static int siw_tx_hdt(struct siw_iwarp_tx *c_tx, struct socket *s)
                                                page_address(p) + fp_off,
                                                plen);
                        } else {
-                               u64 pa = ((sge->laddr + sge_off) & PAGE_MASK);
+                               u64 va = sge->laddr + sge_off;
 
-                               page_array[seg] = virt_to_page(pa);
+                               page_array[seg] = virt_to_page(va & PAGE_MASK);
                                if (do_crc)
                                        crypto_shash_update(
                                                c_tx->mpa_crc_hd,
-                                               (void *)(sge->laddr + sge_off),
+                                               (void *)(uintptr_t)va,
                                                plen);
                        }
 
@@ -543,10 +541,7 @@ static int siw_tx_hdt(struct siw_iwarp_tx *c_tx, struct socket *s)
 
                        if (++seg > (int)MAX_ARRAY) {
                                siw_dbg_qp(tx_qp(c_tx), "to many fragments\n");
-                               if (!is_kva && !c_tx->use_sendpage) {
-                                       siw_unmap_pages(page_array, hdr_len,
-                                                       seg - 1);
-                               }
+                               siw_unmap_pages(page_array, kmap_mask);
                                wqe->processed -= c_tx->bytes_unsent;
                                rv = -EMSGSIZE;
                                goto done_crc;
@@ -597,8 +592,7 @@ sge_done:
        } else {
                rv = kernel_sendmsg(s, &msg, iov, seg + 1,
                                    hdr_len + data_len + trl_len);
-               if (!is_kva)
-                       siw_unmap_pages(page_array, hdr_len, seg);
+               siw_unmap_pages(page_array, kmap_mask);
        }
        if (rv < (int)hdr_len) {
                /* Not even complete hdr pushed or negative rv */
@@ -829,7 +823,8 @@ static int siw_qp_sq_proc_tx(struct siw_qp *qp, struct siw_wqe *wqe)
                                        rv = -EINVAL;
                                        goto tx_error;
                                }
-                               wqe->sqe.sge[0].laddr = (u64)&wqe->sqe.sge[1];
+                               wqe->sqe.sge[0].laddr =
+                                       (u64)(uintptr_t)&wqe->sqe.sge[1];
                        }
                }
                wqe->wr_status = SIW_WR_INPROGRESS;
@@ -924,7 +919,7 @@ tx_error:
 
 static int siw_fastreg_mr(struct ib_pd *pd, struct siw_sqe *sqe)
 {
-       struct ib_mr *base_mr = (struct ib_mr *)sqe->base_mr;
+       struct ib_mr *base_mr = (struct ib_mr *)(uintptr_t)sqe->base_mr;
        struct siw_device *sdev = to_siw_dev(pd->device);
        struct siw_mem *mem = siw_mem_id2obj(sdev, sqe->rkey  >> 8);
        int rv = 0;
@@ -954,8 +949,7 @@ static int siw_fastreg_mr(struct ib_pd *pd, struct siw_sqe *sqe)
        mem->stag = sqe->rkey;
        mem->perms = sqe->access;
 
-       siw_dbg_mem(mem, "STag now valid, MR va: 0x%016llx -> 0x%016llx\n",
-                   mem->va, base_mr->iova);
+       siw_dbg_mem(mem, "STag 0x%08x now valid\n", sqe->rkey);
        mem->va = base_mr->iova;
        mem->stag_valid = 1;
 out:
index e7f3a2379d9d87858ddb83bd7abce843ed330a7a..da52c90e06d48edf8d4dab77680c42aee324621d 100644 (file)
@@ -424,8 +424,7 @@ struct ib_qp *siw_create_qp(struct ib_pd *pd,
                 */
                qp->srq = to_siw_srq(attrs->srq);
                qp->attrs.rq_size = 0;
-               siw_dbg(base_dev, "QP [%u]: [SRQ 0x%p] attached\n",
-                       qp->qp_num, qp->srq);
+               siw_dbg(base_dev, "QP [%u]: SRQ attached\n", qp->qp_num);
        } else if (num_rqe) {
                if (qp->kernel_verbs)
                        qp->recvq = vzalloc(num_rqe * sizeof(struct siw_rqe));
@@ -610,7 +609,7 @@ int siw_destroy_qp(struct ib_qp *base_qp, struct ib_udata *udata)
                                          base_ucontext);
        struct siw_qp_attrs qp_attrs;
 
-       siw_dbg_qp(qp, "state %d, cep 0x%p\n", qp->attrs.state, qp->cep);
+       siw_dbg_qp(qp, "state %d\n", qp->attrs.state);
 
        /*
         * Mark QP as in process of destruction to prevent from
@@ -662,7 +661,7 @@ static int siw_copy_inline_sgl(const struct ib_send_wr *core_wr,
        void *kbuf = &sqe->sge[1];
        int num_sge = core_wr->num_sge, bytes = 0;
 
-       sqe->sge[0].laddr = (u64)kbuf;
+       sqe->sge[0].laddr = (uintptr_t)kbuf;
        sqe->sge[0].lkey = 0;
 
        while (num_sge--) {
@@ -825,7 +824,7 @@ int siw_post_send(struct ib_qp *base_qp, const struct ib_send_wr *wr,
                        break;
 
                case IB_WR_REG_MR:
-                       sqe->base_mr = (uint64_t)reg_wr(wr)->mr;
+                       sqe->base_mr = (uintptr_t)reg_wr(wr)->mr;
                        sqe->rkey = reg_wr(wr)->key;
                        sqe->access = reg_wr(wr)->access & IWARP_ACCESS_MASK;
                        sqe->opcode = SIW_OP_REG_MR;
@@ -842,8 +841,9 @@ int siw_post_send(struct ib_qp *base_qp, const struct ib_send_wr *wr,
                        rv = -EINVAL;
                        break;
                }
-               siw_dbg_qp(qp, "opcode %d, flags 0x%x, wr_id 0x%p\n",
-                          sqe->opcode, sqe->flags, (void *)sqe->id);
+               siw_dbg_qp(qp, "opcode %d, flags 0x%x, wr_id 0x%pK\n",
+                          sqe->opcode, sqe->flags,
+                          (void *)(uintptr_t)sqe->id);
 
                if (unlikely(rv < 0))
                        break;
@@ -1205,8 +1205,8 @@ struct ib_mr *siw_reg_user_mr(struct ib_pd *pd, u64 start, u64 len,
        unsigned long mem_limit = rlimit(RLIMIT_MEMLOCK);
        int rv;
 
-       siw_dbg_pd(pd, "start: 0x%016llx, va: 0x%016llx, len: %llu\n",
-                  (unsigned long long)start, (unsigned long long)rnic_va,
+       siw_dbg_pd(pd, "start: 0x%pK, va: 0x%pK, len: %llu\n",
+                  (void *)(uintptr_t)start, (void *)(uintptr_t)rnic_va,
                   (unsigned long long)len);
 
        if (atomic_inc_return(&sdev->num_mr) > SIW_MAX_MR) {
@@ -1363,7 +1363,7 @@ int siw_map_mr_sg(struct ib_mr *base_mr, struct scatterlist *sl, int num_sle,
        struct siw_mem *mem = mr->mem;
        struct siw_pbl *pbl = mem->pbl;
        struct siw_pble *pble;
-       u64 pbl_size;
+       unsigned long pbl_size;
        int i, rv;
 
        if (!pbl) {
@@ -1402,16 +1402,18 @@ int siw_map_mr_sg(struct ib_mr *base_mr, struct scatterlist *sl, int num_sle,
                        pbl_size += sg_dma_len(slp);
                }
                siw_dbg_mem(mem,
-                       "sge[%d], size %llu, addr 0x%016llx, total %llu\n",
-                       i, pble->size, pble->addr, pbl_size);
+                       "sge[%d], size %u, addr 0x%p, total %lu\n",
+                       i, pble->size, (void *)(uintptr_t)pble->addr,
+                       pbl_size);
        }
        rv = ib_sg_to_pages(base_mr, sl, num_sle, sg_off, siw_set_pbl_page);
        if (rv > 0) {
                mem->len = base_mr->length;
                mem->va = base_mr->iova;
                siw_dbg_mem(mem,
-                       "%llu bytes, start 0x%016llx, %u SLE to %u entries\n",
-                       mem->len, mem->va, num_sle, pbl->num_buf);
+                       "%llu bytes, start 0x%pK, %u SLE to %u entries\n",
+                       mem->len, (void *)(uintptr_t)mem->va, num_sle,
+                       pbl->num_buf);
        }
        return rv;
 }
@@ -1529,7 +1531,7 @@ int siw_create_srq(struct ib_srq *base_srq,
        }
        spin_lock_init(&srq->lock);
 
-       siw_dbg_pd(base_srq->pd, "[SRQ 0x%p]: success\n", srq);
+       siw_dbg_pd(base_srq->pd, "[SRQ]: success\n");
 
        return 0;
 
@@ -1650,8 +1652,7 @@ int siw_post_srq_recv(struct ib_srq *base_srq, const struct ib_recv_wr *wr,
 
        if (unlikely(!srq->kernel_verbs)) {
                siw_dbg_pd(base_srq->pd,
-                          "[SRQ 0x%p]: no kernel post_recv for mapped srq\n",
-                          srq);
+                          "[SRQ]: no kernel post_recv for mapped srq\n");
                rv = -EINVAL;
                goto out;
        }
@@ -1673,8 +1674,7 @@ int siw_post_srq_recv(struct ib_srq *base_srq, const struct ib_recv_wr *wr,
                }
                if (unlikely(wr->num_sge > srq->max_sge)) {
                        siw_dbg_pd(base_srq->pd,
-                                  "[SRQ 0x%p]: too many sge's: %d\n", srq,
-                                  wr->num_sge);
+                                  "[SRQ]: too many sge's: %d\n", wr->num_sge);
                        rv = -EINVAL;
                        break;
                }
@@ -1693,7 +1693,7 @@ int siw_post_srq_recv(struct ib_srq *base_srq, const struct ib_recv_wr *wr,
        spin_unlock_irqrestore(&srq->lock, flags);
 out:
        if (unlikely(rv < 0)) {
-               siw_dbg_pd(base_srq->pd, "[SRQ 0x%p]: error %d\n", srq, rv);
+               siw_dbg_pd(base_srq->pd, "[SRQ]: error %d\n", rv);
                *bad_wr = wr;
        }
        return rv;
index 88ae7c2ac3c817ce983b9fc801a8cacd2aa7b52f..e486a8a74c40c710de93a6de132e15089043d3a3 100644 (file)
@@ -237,40 +237,17 @@ static void hv_kbd_handle_received_packet(struct hv_device *hv_dev,
 
 static void hv_kbd_on_channel_callback(void *context)
 {
+       struct vmpacket_descriptor *desc;
        struct hv_device *hv_dev = context;
-       void *buffer;
-       int bufferlen = 0x100; /* Start with sensible size */
        u32 bytes_recvd;
        u64 req_id;
-       int error;
 
-       buffer = kmalloc(bufferlen, GFP_ATOMIC);
-       if (!buffer)
-               return;
-
-       while (1) {
-               error = vmbus_recvpacket_raw(hv_dev->channel, buffer, bufferlen,
-                                            &bytes_recvd, &req_id);
-               switch (error) {
-               case 0:
-                       if (bytes_recvd == 0) {
-                               kfree(buffer);
-                               return;
-                       }
-
-                       hv_kbd_handle_received_packet(hv_dev, buffer,
-                                                     bytes_recvd, req_id);
-                       break;
+       foreach_vmbus_pkt(desc, hv_dev->channel) {
+               bytes_recvd = desc->len8 * 8;
+               req_id = desc->trans_id;
 
-               case -ENOBUFS:
-                       kfree(buffer);
-                       /* Handle large packet */
-                       bufferlen = bytes_recvd;
-                       buffer = kmalloc(bytes_recvd, GFP_ATOMIC);
-                       if (!buffer)
-                               return;
-                       break;
-               }
+               hv_kbd_handle_received_packet(hv_dev, desc, bytes_recvd,
+                                             req_id);
        }
 }
 
index d991d40f797fb62e9f6659060c1e92d4abb3bddc..f68a62c3c32b55e1414ee5eff0cc34a452f38489 100644 (file)
@@ -965,10 +965,13 @@ static void *iommu_dma_alloc_pages(struct device *dev, size_t size,
 {
        bool coherent = dev_is_dma_coherent(dev);
        size_t alloc_size = PAGE_ALIGN(size);
+       int node = dev_to_node(dev);
        struct page *page = NULL;
        void *cpu_addr;
 
        page = dma_alloc_contiguous(dev, alloc_size, gfp);
+       if (!page)
+               page = alloc_pages_node(node, gfp, get_order(alloc_size));
        if (!page)
                return NULL;
 
index b6b5acc92ca2da725de6a7b0f867c7c83b77d464..2a48ea3f1b30d4adfc6581dff3d1cfe1a088b86a 100644 (file)
@@ -1599,7 +1599,9 @@ dm_bufio_shrink_scan(struct shrinker *shrink, struct shrink_control *sc)
        unsigned long freed;
 
        c = container_of(shrink, struct dm_bufio_client, shrinker);
-       if (!dm_bufio_trylock(c))
+       if (sc->gfp_mask & __GFP_FS)
+               dm_bufio_lock(c);
+       else if (!dm_bufio_trylock(c))
                return SHRINK_STOP;
 
        freed  = __scan(c, sc->nr_to_scan, sc->gfp_mask);
index 845f376a72d9c63f0adced15704e8d7ab979715e..8288887b7f948c31a471358f5de813af00735070 100644 (file)
@@ -25,6 +25,7 @@ struct dust_device {
        unsigned long long badblock_count;
        spinlock_t dust_lock;
        unsigned int blksz;
+       int sect_per_block_shift;
        unsigned int sect_per_block;
        sector_t start;
        bool fail_read_on_bb:1;
@@ -79,7 +80,7 @@ static int dust_remove_block(struct dust_device *dd, unsigned long long block)
        unsigned long flags;
 
        spin_lock_irqsave(&dd->dust_lock, flags);
-       bblock = dust_rb_search(&dd->badblocklist, block * dd->sect_per_block);
+       bblock = dust_rb_search(&dd->badblocklist, block);
 
        if (bblock == NULL) {
                if (!dd->quiet_mode) {
@@ -113,7 +114,7 @@ static int dust_add_block(struct dust_device *dd, unsigned long long block)
        }
 
        spin_lock_irqsave(&dd->dust_lock, flags);
-       bblock->bb = block * dd->sect_per_block;
+       bblock->bb = block;
        if (!dust_rb_insert(&dd->badblocklist, bblock)) {
                if (!dd->quiet_mode) {
                        DMERR("%s: block %llu already in badblocklist",
@@ -138,7 +139,7 @@ static int dust_query_block(struct dust_device *dd, unsigned long long block)
        unsigned long flags;
 
        spin_lock_irqsave(&dd->dust_lock, flags);
-       bblock = dust_rb_search(&dd->badblocklist, block * dd->sect_per_block);
+       bblock = dust_rb_search(&dd->badblocklist, block);
        if (bblock != NULL)
                DMINFO("%s: block %llu found in badblocklist", __func__, block);
        else
@@ -165,6 +166,7 @@ static int dust_map_read(struct dust_device *dd, sector_t thisblock,
        int ret = DM_MAPIO_REMAPPED;
 
        if (fail_read_on_bb) {
+               thisblock >>= dd->sect_per_block_shift;
                spin_lock_irqsave(&dd->dust_lock, flags);
                ret = __dust_map_read(dd, thisblock);
                spin_unlock_irqrestore(&dd->dust_lock, flags);
@@ -195,6 +197,7 @@ static int dust_map_write(struct dust_device *dd, sector_t thisblock,
        unsigned long flags;
 
        if (fail_read_on_bb) {
+               thisblock >>= dd->sect_per_block_shift;
                spin_lock_irqsave(&dd->dust_lock, flags);
                __dust_map_write(dd, thisblock);
                spin_unlock_irqrestore(&dd->dust_lock, flags);
@@ -331,6 +334,8 @@ static int dust_ctr(struct dm_target *ti, unsigned int argc, char **argv)
        dd->blksz = blksz;
        dd->start = tmp;
 
+       dd->sect_per_block_shift = __ffs(sect_per_block);
+
        /*
         * Whether to fail a read on a "bad" block.
         * Defaults to false; enabled later by message.
index b1b0de402dfc36eb937cc1967dcf4a341057b576..9118ab85cb3ad96414805059f7ec2b96df1a29b3 100644 (file)
@@ -1943,7 +1943,22 @@ offload_to_thread:
                        queue_work(ic->wait_wq, &dio->work);
                        return;
                }
+               if (journal_read_pos != NOT_FOUND)
+                       dio->range.n_sectors = ic->sectors_per_block;
                wait_and_add_new_range(ic, &dio->range);
+               /*
+                * wait_and_add_new_range drops the spinlock, so the journal
+                * may have been changed arbitrarily. We need to recheck.
+                * To simplify the code, we restrict I/O size to just one block.
+                */
+               if (journal_read_pos != NOT_FOUND) {
+                       sector_t next_sector;
+                       unsigned new_pos = find_journal_node(ic, dio->range.logical_sector, &next_sector);
+                       if (unlikely(new_pos != journal_read_pos)) {
+                               remove_range_unlocked(ic, &dio->range);
+                               goto retry;
+                       }
+               }
        }
        spin_unlock_irq(&ic->endio_wait.lock);
 
index df2011de7be268131211025e227fc5d989334161..1bbe4a34ef4ca62ff59984051ca30be2421c4c6c 100644 (file)
@@ -566,8 +566,10 @@ static int run_io_job(struct kcopyd_job *job)
         * no point in continuing.
         */
        if (test_bit(DM_KCOPYD_WRITE_SEQ, &job->flags) &&
-           job->master_job->write_err)
+           job->master_job->write_err) {
+               job->write_err = job->master_job->write_err;
                return -EIO;
+       }
 
        io_job_start(job->kc->throttle);
 
@@ -619,6 +621,7 @@ static int process_jobs(struct list_head *jobs, struct dm_kcopyd_client *kc,
                        else
                                job->read_err = 1;
                        push(&kc->complete_jobs, job);
+                       wake(kc);
                        break;
                }
 
index 8a60a4a070ac99669e947e5a68a9e3cf1ad8346e..1f933dd197cdf82e14fc242290e5a3268f478b5f 100644 (file)
@@ -3194,7 +3194,7 @@ static int raid_ctr(struct dm_target *ti, unsigned int argc, char **argv)
                          */
                        r = rs_prepare_reshape(rs);
                        if (r)
-                               return r;
+                               goto bad;
 
                        /* Reshaping ain't recovery, so disable recovery */
                        rs_setup_recovery(rs, MaxSector);
index 7b6c3ee9e75526fbbd7e809394bca38fbfca3fcb..8820931ec7d2d70cf90d1c1f65fbdb8881fd559a 100644 (file)
@@ -1342,7 +1342,7 @@ void dm_table_event(struct dm_table *t)
 }
 EXPORT_SYMBOL(dm_table_event);
 
-sector_t dm_table_get_size(struct dm_table *t)
+inline sector_t dm_table_get_size(struct dm_table *t)
 {
        return t->num_targets ? (t->highs[t->num_targets - 1] + 1) : 0;
 }
@@ -1367,6 +1367,9 @@ struct dm_target *dm_table_find_target(struct dm_table *t, sector_t sector)
        unsigned int l, n = 0, k = 0;
        sector_t *node;
 
+       if (unlikely(sector >= dm_table_get_size(t)))
+               return &t->targets[t->num_targets];
+
        for (l = 0; l < t->depth; l++) {
                n = get_child(n, k);
                node = get_node(t, l, n);
index 8545dcee9fd0498d1334656881a02fac426276f5..595a73110e1731efbabd33e14c0f4ec2401da4d8 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-only
 /*
  * Copyright (C) 2017 Western Digital Corporation or its affiliates.
  *
@@ -34,7 +35,7 @@
  *    (1) Super block (1 block)
  *    (2) Chunk mapping table (nr_map_blocks)
  *    (3) Bitmap blocks (nr_bitmap_blocks)
- * All metadata blocks are stored in conventional zones, starting from the
+ * All metadata blocks are stored in conventional zones, starting from
  * the first conventional zone found on disk.
  */
 struct dmz_super {
@@ -233,7 +234,7 @@ void dmz_unlock_map(struct dmz_metadata *zmd)
  * Lock/unlock metadata access. This is a "read" lock on a semaphore
  * that prevents metadata flush from running while metadata are being
  * modified. The actual metadata write mutual exclusion is achieved with
- * the map lock and zone styate management (active and reclaim state are
+ * the map lock and zone state management (active and reclaim state are
  * mutually exclusive).
  */
 void dmz_lock_metadata(struct dmz_metadata *zmd)
@@ -402,15 +403,18 @@ static struct dmz_mblock *dmz_get_mblock_slow(struct dmz_metadata *zmd,
        sector_t block = zmd->sb[zmd->mblk_primary].block + mblk_no;
        struct bio *bio;
 
+       if (dmz_bdev_is_dying(zmd->dev))
+               return ERR_PTR(-EIO);
+
        /* Get a new block and a BIO to read it */
        mblk = dmz_alloc_mblock(zmd, mblk_no);
        if (!mblk)
-               return NULL;
+               return ERR_PTR(-ENOMEM);
 
        bio = bio_alloc(GFP_NOIO, 1);
        if (!bio) {
                dmz_free_mblock(zmd, mblk);
-               return NULL;
+               return ERR_PTR(-ENOMEM);
        }
 
        spin_lock(&zmd->mblk_lock);
@@ -541,8 +545,8 @@ static struct dmz_mblock *dmz_get_mblock(struct dmz_metadata *zmd,
        if (!mblk) {
                /* Cache miss: read the block from disk */
                mblk = dmz_get_mblock_slow(zmd, mblk_no);
-               if (!mblk)
-                       return ERR_PTR(-ENOMEM);
+               if (IS_ERR(mblk))
+                       return mblk;
        }
 
        /* Wait for on-going read I/O and check for error */
@@ -570,16 +574,19 @@ static void dmz_dirty_mblock(struct dmz_metadata *zmd, struct dmz_mblock *mblk)
 /*
  * Issue a metadata block write BIO.
  */
-static void dmz_write_mblock(struct dmz_metadata *zmd, struct dmz_mblock *mblk,
-                            unsigned int set)
+static int dmz_write_mblock(struct dmz_metadata *zmd, struct dmz_mblock *mblk,
+                           unsigned int set)
 {
        sector_t block = zmd->sb[set].block + mblk->no;
        struct bio *bio;
 
+       if (dmz_bdev_is_dying(zmd->dev))
+               return -EIO;
+
        bio = bio_alloc(GFP_NOIO, 1);
        if (!bio) {
                set_bit(DMZ_META_ERROR, &mblk->state);
-               return;
+               return -ENOMEM;
        }
 
        set_bit(DMZ_META_WRITING, &mblk->state);
@@ -591,6 +598,8 @@ static void dmz_write_mblock(struct dmz_metadata *zmd, struct dmz_mblock *mblk,
        bio_set_op_attrs(bio, REQ_OP_WRITE, REQ_META | REQ_PRIO);
        bio_add_page(bio, mblk->page, DMZ_BLOCK_SIZE, 0);
        submit_bio(bio);
+
+       return 0;
 }
 
 /*
@@ -602,6 +611,9 @@ static int dmz_rdwr_block(struct dmz_metadata *zmd, int op, sector_t block,
        struct bio *bio;
        int ret;
 
+       if (dmz_bdev_is_dying(zmd->dev))
+               return -EIO;
+
        bio = bio_alloc(GFP_NOIO, 1);
        if (!bio)
                return -ENOMEM;
@@ -659,22 +671,29 @@ static int dmz_write_dirty_mblocks(struct dmz_metadata *zmd,
 {
        struct dmz_mblock *mblk;
        struct blk_plug plug;
-       int ret = 0;
+       int ret = 0, nr_mblks_submitted = 0;
 
        /* Issue writes */
        blk_start_plug(&plug);
-       list_for_each_entry(mblk, write_list, link)
-               dmz_write_mblock(zmd, mblk, set);
+       list_for_each_entry(mblk, write_list, link) {
+               ret = dmz_write_mblock(zmd, mblk, set);
+               if (ret)
+                       break;
+               nr_mblks_submitted++;
+       }
        blk_finish_plug(&plug);
 
        /* Wait for completion */
        list_for_each_entry(mblk, write_list, link) {
+               if (!nr_mblks_submitted)
+                       break;
                wait_on_bit_io(&mblk->state, DMZ_META_WRITING,
                               TASK_UNINTERRUPTIBLE);
                if (test_bit(DMZ_META_ERROR, &mblk->state)) {
                        clear_bit(DMZ_META_ERROR, &mblk->state);
                        ret = -EIO;
                }
+               nr_mblks_submitted--;
        }
 
        /* Flush drive cache (this will also sync data) */
@@ -736,6 +755,11 @@ int dmz_flush_metadata(struct dmz_metadata *zmd)
         */
        dmz_lock_flush(zmd);
 
+       if (dmz_bdev_is_dying(zmd->dev)) {
+               ret = -EIO;
+               goto out;
+       }
+
        /* Get dirty blocks */
        spin_lock(&zmd->mblk_lock);
        list_splice_init(&zmd->mblk_dirty_list, &write_list);
@@ -1542,7 +1566,7 @@ static struct dm_zone *dmz_get_rnd_zone_for_reclaim(struct dmz_metadata *zmd)
        struct dm_zone *zone;
 
        if (list_empty(&zmd->map_rnd_list))
-               return NULL;
+               return ERR_PTR(-EBUSY);
 
        list_for_each_entry(zone, &zmd->map_rnd_list, link) {
                if (dmz_is_buf(zone))
@@ -1553,7 +1577,7 @@ static struct dm_zone *dmz_get_rnd_zone_for_reclaim(struct dmz_metadata *zmd)
                        return dzone;
        }
 
-       return NULL;
+       return ERR_PTR(-EBUSY);
 }
 
 /*
@@ -1564,7 +1588,7 @@ static struct dm_zone *dmz_get_seq_zone_for_reclaim(struct dmz_metadata *zmd)
        struct dm_zone *zone;
 
        if (list_empty(&zmd->map_seq_list))
-               return NULL;
+               return ERR_PTR(-EBUSY);
 
        list_for_each_entry(zone, &zmd->map_seq_list, link) {
                if (!zone->bzone)
@@ -1573,7 +1597,7 @@ static struct dm_zone *dmz_get_seq_zone_for_reclaim(struct dmz_metadata *zmd)
                        return zone;
        }
 
-       return NULL;
+       return ERR_PTR(-EBUSY);
 }
 
 /*
@@ -1628,9 +1652,13 @@ again:
                if (op != REQ_OP_WRITE)
                        goto out;
 
-               /* Alloate a random zone */
+               /* Allocate a random zone */
                dzone = dmz_alloc_zone(zmd, DMZ_ALLOC_RND);
                if (!dzone) {
+                       if (dmz_bdev_is_dying(zmd->dev)) {
+                               dzone = ERR_PTR(-EIO);
+                               goto out;
+                       }
                        dmz_wait_for_free_zones(zmd);
                        goto again;
                }
@@ -1725,9 +1753,13 @@ again:
        if (bzone)
                goto out;
 
-       /* Alloate a random zone */
+       /* Allocate a random zone */
        bzone = dmz_alloc_zone(zmd, DMZ_ALLOC_RND);
        if (!bzone) {
+               if (dmz_bdev_is_dying(zmd->dev)) {
+                       bzone = ERR_PTR(-EIO);
+                       goto out;
+               }
                dmz_wait_for_free_zones(zmd);
                goto again;
        }
index edf4b95eb0750dc6485513d49c240b2982017114..d240d7ca8a8ae6f35cc23f63c69070a931bb327a 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-only
 /*
  * Copyright (C) 2017 Western Digital Corporation or its affiliates.
  *
@@ -37,7 +38,7 @@ enum {
 /*
  * Number of seconds of target BIO inactivity to consider the target idle.
  */
-#define DMZ_IDLE_PERIOD                (10UL * HZ)
+#define DMZ_IDLE_PERIOD                        (10UL * HZ)
 
 /*
  * Percentage of unmapped (free) random zones below which reclaim starts
@@ -134,6 +135,9 @@ static int dmz_reclaim_copy(struct dmz_reclaim *zrc,
                set_bit(DM_KCOPYD_WRITE_SEQ, &flags);
 
        while (block < end_block) {
+               if (dev->flags & DMZ_BDEV_DYING)
+                       return -EIO;
+
                /* Get a valid region from the source zone */
                ret = dmz_first_valid_block(zmd, src_zone, &block);
                if (ret <= 0)
@@ -215,7 +219,7 @@ static int dmz_reclaim_buf(struct dmz_reclaim *zrc, struct dm_zone *dzone)
 
        dmz_unlock_flush(zmd);
 
-       return 0;
+       return ret;
 }
 
 /*
@@ -259,7 +263,7 @@ static int dmz_reclaim_seq_data(struct dmz_reclaim *zrc, struct dm_zone *dzone)
 
        dmz_unlock_flush(zmd);
 
-       return 0;
+       return ret;
 }
 
 /*
@@ -312,7 +316,7 @@ static int dmz_reclaim_rnd_data(struct dmz_reclaim *zrc, struct dm_zone *dzone)
 
        dmz_unlock_flush(zmd);
 
-       return 0;
+       return ret;
 }
 
 /*
@@ -334,7 +338,7 @@ static void dmz_reclaim_empty(struct dmz_reclaim *zrc, struct dm_zone *dzone)
 /*
  * Find a candidate zone for reclaim and process it.
  */
-static void dmz_reclaim(struct dmz_reclaim *zrc)
+static int dmz_do_reclaim(struct dmz_reclaim *zrc)
 {
        struct dmz_metadata *zmd = zrc->metadata;
        struct dm_zone *dzone;
@@ -344,8 +348,8 @@ static void dmz_reclaim(struct dmz_reclaim *zrc)
 
        /* Get a data zone */
        dzone = dmz_get_zone_for_reclaim(zmd);
-       if (!dzone)
-               return;
+       if (IS_ERR(dzone))
+               return PTR_ERR(dzone);
 
        start = jiffies;
 
@@ -391,13 +395,20 @@ static void dmz_reclaim(struct dmz_reclaim *zrc)
 out:
        if (ret) {
                dmz_unlock_zone_reclaim(dzone);
-               return;
+               return ret;
        }
 
-       (void) dmz_flush_metadata(zrc->metadata);
+       ret = dmz_flush_metadata(zrc->metadata);
+       if (ret) {
+               dmz_dev_debug(zrc->dev,
+                             "Metadata flush for zone %u failed, err %d\n",
+                             dmz_id(zmd, rzone), ret);
+               return ret;
+       }
 
        dmz_dev_debug(zrc->dev, "Reclaimed zone %u in %u ms",
                      dmz_id(zmd, rzone), jiffies_to_msecs(jiffies - start));
+       return 0;
 }
 
 /*
@@ -427,7 +438,7 @@ static bool dmz_should_reclaim(struct dmz_reclaim *zrc)
                return false;
 
        /*
-        * If the percentage of unmappped random zones is low,
+        * If the percentage of unmapped random zones is low,
         * reclaim even if the target is busy.
         */
        return p_unmap_rnd <= DMZ_RECLAIM_LOW_UNMAP_RND;
@@ -442,6 +453,10 @@ static void dmz_reclaim_work(struct work_struct *work)
        struct dmz_metadata *zmd = zrc->metadata;
        unsigned int nr_rnd, nr_unmap_rnd;
        unsigned int p_unmap_rnd;
+       int ret;
+
+       if (dmz_bdev_is_dying(zrc->dev))
+               return;
 
        if (!dmz_should_reclaim(zrc)) {
                mod_delayed_work(zrc->wq, &zrc->work, DMZ_IDLE_PERIOD);
@@ -471,7 +486,17 @@ static void dmz_reclaim_work(struct work_struct *work)
                      (dmz_target_idle(zrc) ? "Idle" : "Busy"),
                      p_unmap_rnd, nr_unmap_rnd, nr_rnd);
 
-       dmz_reclaim(zrc);
+       ret = dmz_do_reclaim(zrc);
+       if (ret) {
+               dmz_dev_debug(zrc->dev, "Reclaim error %d\n", ret);
+               if (ret == -EIO)
+                       /*
+                        * LLD might be performing some error handling sequence
+                        * at the underlying device. To not interfere, do not
+                        * attempt to schedule the next reclaim run immediately.
+                        */
+                       return;
+       }
 
        dmz_schedule_reclaim(zrc);
 }
index 51d029bbb740c4f032ea63005611b194fcc5cee8..31478fef6032daf0c84eb8db29263816f91117b3 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-only
 /*
  * Copyright (C) 2017 Western Digital Corporation or its affiliates.
  *
@@ -133,6 +134,8 @@ static int dmz_submit_bio(struct dmz_target *dmz, struct dm_zone *zone,
 
        refcount_inc(&bioctx->ref);
        generic_make_request(clone);
+       if (clone->bi_status == BLK_STS_IOERR)
+               return -EIO;
 
        if (bio_op(bio) == REQ_OP_WRITE && dmz_is_seq(zone))
                zone->wp_block += nr_blocks;
@@ -277,8 +280,8 @@ static int dmz_handle_buffered_write(struct dmz_target *dmz,
 
        /* Get the buffer zone. One will be allocated if needed */
        bzone = dmz_get_chunk_buffer(zmd, zone);
-       if (!bzone)
-               return -ENOSPC;
+       if (IS_ERR(bzone))
+               return PTR_ERR(bzone);
 
        if (dmz_is_readonly(bzone))
                return -EROFS;
@@ -389,6 +392,11 @@ static void dmz_handle_bio(struct dmz_target *dmz, struct dm_chunk_work *cw,
 
        dmz_lock_metadata(zmd);
 
+       if (dmz->dev->flags & DMZ_BDEV_DYING) {
+               ret = -EIO;
+               goto out;
+       }
+
        /*
         * Get the data zone mapping the chunk. There may be no
         * mapping for read and discard. If a mapping is obtained,
@@ -493,6 +501,8 @@ static void dmz_flush_work(struct work_struct *work)
 
        /* Flush dirty metadata blocks */
        ret = dmz_flush_metadata(dmz->metadata);
+       if (ret)
+               dmz_dev_debug(dmz->dev, "Metadata flush failed, rc=%d\n", ret);
 
        /* Process queued flush requests */
        while (1) {
@@ -513,22 +523,24 @@ static void dmz_flush_work(struct work_struct *work)
  * Get a chunk work and start it to process a new BIO.
  * If the BIO chunk has no work yet, create one.
  */
-static void dmz_queue_chunk_work(struct dmz_target *dmz, struct bio *bio)
+static int dmz_queue_chunk_work(struct dmz_target *dmz, struct bio *bio)
 {
        unsigned int chunk = dmz_bio_chunk(dmz->dev, bio);
        struct dm_chunk_work *cw;
+       int ret = 0;
 
        mutex_lock(&dmz->chunk_lock);
 
        /* Get the BIO chunk work. If one is not active yet, create one */
        cw = radix_tree_lookup(&dmz->chunk_rxtree, chunk);
        if (!cw) {
-               int ret;
 
                /* Create a new chunk work */
                cw = kmalloc(sizeof(struct dm_chunk_work), GFP_NOIO);
-               if (!cw)
+               if (unlikely(!cw)) {
+                       ret = -ENOMEM;
                        goto out;
+               }
 
                INIT_WORK(&cw->work, dmz_chunk_work);
                refcount_set(&cw->refcount, 0);
@@ -539,7 +551,6 @@ static void dmz_queue_chunk_work(struct dmz_target *dmz, struct bio *bio)
                ret = radix_tree_insert(&dmz->chunk_rxtree, chunk, cw);
                if (unlikely(ret)) {
                        kfree(cw);
-                       cw = NULL;
                        goto out;
                }
        }
@@ -547,10 +558,38 @@ static void dmz_queue_chunk_work(struct dmz_target *dmz, struct bio *bio)
        bio_list_add(&cw->bio_list, bio);
        dmz_get_chunk_work(cw);
 
+       dmz_reclaim_bio_acc(dmz->reclaim);
        if (queue_work(dmz->chunk_wq, &cw->work))
                dmz_get_chunk_work(cw);
 out:
        mutex_unlock(&dmz->chunk_lock);
+       return ret;
+}
+
+/*
+ * Check the backing device availability. If it's on the way out,
+ * start failing I/O. Reclaim and metadata components also call this
+ * function to cleanly abort operation in the event of such failure.
+ */
+bool dmz_bdev_is_dying(struct dmz_dev *dmz_dev)
+{
+       struct gendisk *disk;
+
+       if (!(dmz_dev->flags & DMZ_BDEV_DYING)) {
+               disk = dmz_dev->bdev->bd_disk;
+               if (blk_queue_dying(bdev_get_queue(dmz_dev->bdev))) {
+                       dmz_dev_warn(dmz_dev, "Backing device queue dying");
+                       dmz_dev->flags |= DMZ_BDEV_DYING;
+               } else if (disk->fops->check_events) {
+                       if (disk->fops->check_events(disk, 0) &
+                                       DISK_EVENT_MEDIA_CHANGE) {
+                               dmz_dev_warn(dmz_dev, "Backing device offline");
+                               dmz_dev->flags |= DMZ_BDEV_DYING;
+                       }
+               }
+       }
+
+       return dmz_dev->flags & DMZ_BDEV_DYING;
 }
 
 /*
@@ -564,6 +603,10 @@ static int dmz_map(struct dm_target *ti, struct bio *bio)
        sector_t sector = bio->bi_iter.bi_sector;
        unsigned int nr_sectors = bio_sectors(bio);
        sector_t chunk_sector;
+       int ret;
+
+       if (dmz_bdev_is_dying(dmz->dev))
+               return DM_MAPIO_KILL;
 
        dmz_dev_debug(dev, "BIO op %d sector %llu + %u => chunk %llu, block %llu, %u blocks",
                      bio_op(bio), (unsigned long long)sector, nr_sectors,
@@ -601,8 +644,14 @@ static int dmz_map(struct dm_target *ti, struct bio *bio)
                dm_accept_partial_bio(bio, dev->zone_nr_sectors - chunk_sector);
 
        /* Now ready to handle this BIO */
-       dmz_reclaim_bio_acc(dmz->reclaim);
-       dmz_queue_chunk_work(dmz, bio);
+       ret = dmz_queue_chunk_work(dmz, bio);
+       if (ret) {
+               dmz_dev_debug(dmz->dev,
+                             "BIO op %d, can't process chunk %llu, err %i\n",
+                             bio_op(bio), (u64)dmz_bio_chunk(dmz->dev, bio),
+                             ret);
+               return DM_MAPIO_REQUEUE;
+       }
 
        return DM_MAPIO_SUBMITTED;
 }
@@ -855,6 +904,9 @@ static int dmz_prepare_ioctl(struct dm_target *ti, struct block_device **bdev)
 {
        struct dmz_target *dmz = ti->private;
 
+       if (dmz_bdev_is_dying(dmz->dev))
+               return -ENODEV;
+
        *bdev = dmz->dev->bdev;
 
        return 0;
index ed8de49c9a08263e8ca25ff2979abb2958b4cde0..d8e70b0ade354c7ea6b3e4a262aaac1bc788f43b 100644 (file)
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (C) 2017 Western Digital Corporation or its affiliates.
  *
@@ -56,6 +57,8 @@ struct dmz_dev {
 
        unsigned int            nr_zones;
 
+       unsigned int            flags;
+
        sector_t                zone_nr_sectors;
        unsigned int            zone_nr_sectors_shift;
 
@@ -67,6 +70,9 @@ struct dmz_dev {
                                 (dev)->zone_nr_sectors_shift)
 #define dmz_chunk_block(dev, b)        ((b) & ((dev)->zone_nr_blocks - 1))
 
+/* Device flags. */
+#define DMZ_BDEV_DYING         (1 << 0)
+
 /*
  * Zone descriptor.
  */
@@ -245,4 +251,9 @@ void dmz_resume_reclaim(struct dmz_reclaim *zrc);
 void dmz_reclaim_bio_acc(struct dmz_reclaim *zrc);
 void dmz_schedule_reclaim(struct dmz_reclaim *zrc);
 
+/*
+ * Functions defined in dm-zoned-target.c
+ */
+bool dmz_bdev_is_dying(struct dmz_dev *dmz_dev);
+
 #endif /* DM_ZONED_H */
index 58b319757b1e5a1c274bd98681d6ce229bbbabbe..8aae0624a2971e939fa79acd656f98035049460d 100644 (file)
@@ -628,39 +628,40 @@ static int btree_split_beneath(struct shadow_spine *s, uint64_t key)
 
        new_parent = shadow_current(s);
 
+       pn = dm_block_data(new_parent);
+       size = le32_to_cpu(pn->header.flags) & INTERNAL_NODE ?
+               sizeof(__le64) : s->info->value_type.size;
+
+       /* create & init the left block */
        r = new_block(s->info, &left);
        if (r < 0)
                return r;
 
+       ln = dm_block_data(left);
+       nr_left = le32_to_cpu(pn->header.nr_entries) / 2;
+
+       ln->header.flags = pn->header.flags;
+       ln->header.nr_entries = cpu_to_le32(nr_left);
+       ln->header.max_entries = pn->header.max_entries;
+       ln->header.value_size = pn->header.value_size;
+       memcpy(ln->keys, pn->keys, nr_left * sizeof(pn->keys[0]));
+       memcpy(value_ptr(ln, 0), value_ptr(pn, 0), nr_left * size);
+
+       /* create & init the right block */
        r = new_block(s->info, &right);
        if (r < 0) {
                unlock_block(s->info, left);
                return r;
        }
 
-       pn = dm_block_data(new_parent);
-       ln = dm_block_data(left);
        rn = dm_block_data(right);
-
-       nr_left = le32_to_cpu(pn->header.nr_entries) / 2;
        nr_right = le32_to_cpu(pn->header.nr_entries) - nr_left;
 
-       ln->header.flags = pn->header.flags;
-       ln->header.nr_entries = cpu_to_le32(nr_left);
-       ln->header.max_entries = pn->header.max_entries;
-       ln->header.value_size = pn->header.value_size;
-
        rn->header.flags = pn->header.flags;
        rn->header.nr_entries = cpu_to_le32(nr_right);
        rn->header.max_entries = pn->header.max_entries;
        rn->header.value_size = pn->header.value_size;
-
-       memcpy(ln->keys, pn->keys, nr_left * sizeof(pn->keys[0]));
        memcpy(rn->keys, pn->keys + nr_left, nr_right * sizeof(pn->keys[0]));
-
-       size = le32_to_cpu(pn->header.flags) & INTERNAL_NODE ?
-               sizeof(__le64) : s->info->value_type.size;
-       memcpy(value_ptr(ln, 0), value_ptr(pn, 0), nr_left * size);
        memcpy(value_ptr(rn, 0), value_ptr(pn, nr_left),
               nr_right * size);
 
index aec44924396622729f64e84abda381d24606e14a..25328582cc4820dc29d0e79a8012eeeb8a7fb2f4 100644 (file)
@@ -249,7 +249,7 @@ static int out(struct sm_metadata *smm)
        }
 
        if (smm->recursion_count == 1)
-               apply_bops(smm);
+               r = apply_bops(smm);
 
        smm->recursion_count--;
 
index 895510d40ce4794b149baa9374576cd4a8385ca3..47602af4ee34940a3f5fd381aca7dcf7fd7c1a48 100644 (file)
@@ -81,6 +81,7 @@ static int sa1100_probe_subdev(struct sa_subdev_info *subdev, struct resource *r
        default:
                printk(KERN_WARNING "SA1100 flash: unknown base address "
                       "0x%08lx, assuming CS0\n", phys);
+               /* Fall through */
 
        case SA1100_CS0_PHYS:
                subdev->map.bankwidth = (MSC0 & MSC_RBW) ? 2 : 4;
index 02fd7822c14a4286f1b5ec6379bd22fcd4d21330..931d9d9356869b400c1b653414164a3e5ecb0b51 100644 (file)
@@ -1126,6 +1126,8 @@ static void bond_compute_features(struct bonding *bond)
 done:
        bond_dev->vlan_features = vlan_features;
        bond_dev->hw_enc_features = enc_features | NETIF_F_GSO_ENCAP_ALL |
+                                   NETIF_F_HW_VLAN_CTAG_TX |
+                                   NETIF_F_HW_VLAN_STAG_TX |
                                    NETIF_F_GSO_UDP_L4;
        bond_dev->mpls_features = mpls_features;
        bond_dev->gso_max_segs = gso_max_segs;
index d073baffc20b042d92fbbbcc4657d7fb6cee5c5a..df976b259e43d24dc226d1e347c6338412868fe6 100644 (file)
@@ -1223,12 +1223,8 @@ static int sja1105_fdb_dump(struct dsa_switch *ds, int port,
 {
        struct sja1105_private *priv = ds->priv;
        struct device *dev = ds->dev;
-       u16 rx_vid, tx_vid;
        int i;
 
-       rx_vid = dsa_8021q_rx_vid(ds, port);
-       tx_vid = dsa_8021q_tx_vid(ds, port);
-
        for (i = 0; i < SJA1105_MAX_L2_LOOKUP_COUNT; i++) {
                struct sja1105_l2_lookup_entry l2_lookup = {0};
                u8 macaddr[ETH_ALEN];
index e47ea92e2ae3a320d2b02d51865ade6eccdfcb90..d10b421ed1f19939bb4046ede23d74b55ebb5beb 100644 (file)
@@ -3057,12 +3057,13 @@ int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode, bool keep_link)
        /* if VF indicate to PF this function is going down (PF will delete sp
         * elements and clear initializations
         */
-       if (IS_VF(bp))
+       if (IS_VF(bp)) {
+               bnx2x_clear_vlan_info(bp);
                bnx2x_vfpf_close_vf(bp);
-       else if (unload_mode != UNLOAD_RECOVERY)
+       } else if (unload_mode != UNLOAD_RECOVERY) {
                /* if this is a normal/close unload need to clean up chip*/
                bnx2x_chip_cleanup(bp, unload_mode, keep_link);
-       else {
+       else {
                /* Send the UNLOAD_REQUEST to the MCP */
                bnx2x_send_unload_req(bp, unload_mode);
 
index c2f6e44e9a3f7e75b41f2542fedb9595fa2ef154..8b08cb18e36387e8465dda447f3b42150cab28bb 100644 (file)
@@ -425,6 +425,8 @@ void bnx2x_set_reset_global(struct bnx2x *bp);
 void bnx2x_disable_close_the_gate(struct bnx2x *bp);
 int bnx2x_init_hw_func_cnic(struct bnx2x *bp);
 
+void bnx2x_clear_vlan_info(struct bnx2x *bp);
+
 /**
  * bnx2x_sp_event - handle ramrods completion.
  *
index 2cc14db8f0ec9c1d0ee8b922ea9926320cc5bb96..192ff8d5da3247c5f9f3b2fa0d7382adbdd83fb6 100644 (file)
@@ -8482,11 +8482,21 @@ int bnx2x_set_vlan_one(struct bnx2x *bp, u16 vlan,
        return rc;
 }
 
+void bnx2x_clear_vlan_info(struct bnx2x *bp)
+{
+       struct bnx2x_vlan_entry *vlan;
+
+       /* Mark that hw forgot all entries */
+       list_for_each_entry(vlan, &bp->vlan_reg, link)
+               vlan->hw = false;
+
+       bp->vlan_cnt = 0;
+}
+
 static int bnx2x_del_all_vlans(struct bnx2x *bp)
 {
        struct bnx2x_vlan_mac_obj *vlan_obj = &bp->sp_objs[0].vlan_obj;
        unsigned long ramrod_flags = 0, vlan_flags = 0;
-       struct bnx2x_vlan_entry *vlan;
        int rc;
 
        __set_bit(RAMROD_COMP_WAIT, &ramrod_flags);
@@ -8495,10 +8505,7 @@ static int bnx2x_del_all_vlans(struct bnx2x *bp)
        if (rc)
                return rc;
 
-       /* Mark that hw forgot all entries */
-       list_for_each_entry(vlan, &bp->vlan_reg, link)
-               vlan->hw = false;
-       bp->vlan_cnt = 0;
+       bnx2x_clear_vlan_info(bp);
 
        return 0;
 }
index 7070349915bc5412a52e556de427fb8ed6174480..8dce4069472b6c02ed6d5d9cb58cce5a7b1ddeaf 100644 (file)
@@ -2021,9 +2021,9 @@ static void __bnxt_poll_work_done(struct bnxt *bp, struct bnxt_napi *bnapi)
        if (bnapi->events & BNXT_RX_EVENT) {
                struct bnxt_rx_ring_info *rxr = bnapi->rx_ring;
 
-               bnxt_db_write(bp, &rxr->rx_db, rxr->rx_prod);
                if (bnapi->events & BNXT_AGG_EVENT)
                        bnxt_db_write(bp, &rxr->rx_agg_db, rxr->rx_agg_prod);
+               bnxt_db_write(bp, &rxr->rx_db, rxr->rx_prod);
        }
        bnapi->events = 0;
 }
@@ -5064,6 +5064,7 @@ static void bnxt_set_db(struct bnxt *bp, struct bnxt_db_info *db, u32 ring_type,
 
 static int bnxt_hwrm_ring_alloc(struct bnxt *bp)
 {
+       bool agg_rings = !!(bp->flags & BNXT_FLAG_AGG_RINGS);
        int i, rc = 0;
        u32 type;
 
@@ -5139,7 +5140,9 @@ static int bnxt_hwrm_ring_alloc(struct bnxt *bp)
                if (rc)
                        goto err_out;
                bnxt_set_db(bp, &rxr->rx_db, type, map_idx, ring->fw_ring_id);
-               bnxt_db_write(bp, &rxr->rx_db, rxr->rx_prod);
+               /* If we have agg rings, post agg buffers first. */
+               if (!agg_rings)
+                       bnxt_db_write(bp, &rxr->rx_db, rxr->rx_prod);
                bp->grp_info[map_idx].rx_fw_ring_id = ring->fw_ring_id;
                if (bp->flags & BNXT_FLAG_CHIP_P5) {
                        struct bnxt_cp_ring_info *cpr = &bnapi->cp_ring;
@@ -5158,7 +5161,7 @@ static int bnxt_hwrm_ring_alloc(struct bnxt *bp)
                }
        }
 
-       if (bp->flags & BNXT_FLAG_AGG_RINGS) {
+       if (agg_rings) {
                type = HWRM_RING_ALLOC_AGG;
                for (i = 0; i < bp->rx_nr_rings; i++) {
                        struct bnxt_rx_ring_info *rxr = &bp->rx_ring[i];
@@ -5174,6 +5177,7 @@ static int bnxt_hwrm_ring_alloc(struct bnxt *bp)
                        bnxt_set_db(bp, &rxr->rx_agg_db, type, map_idx,
                                    ring->fw_ring_id);
                        bnxt_db_write(bp, &rxr->rx_agg_db, rxr->rx_agg_prod);
+                       bnxt_db_write(bp, &rxr->rx_db, rxr->rx_prod);
                        bp->grp_info[grp_idx].agg_fw_ring_id = ring->fw_ring_id;
                }
        }
@@ -7016,19 +7020,29 @@ static void bnxt_hwrm_clear_vnic_rss(struct bnxt *bp)
                bnxt_hwrm_vnic_set_rss(bp, i, false);
 }
 
-static void bnxt_hwrm_resource_free(struct bnxt *bp, bool close_path,
-                                   bool irq_re_init)
+static void bnxt_clear_vnic(struct bnxt *bp)
 {
-       if (bp->vnic_info) {
-               bnxt_hwrm_clear_vnic_filter(bp);
+       if (!bp->vnic_info)
+               return;
+
+       bnxt_hwrm_clear_vnic_filter(bp);
+       if (!(bp->flags & BNXT_FLAG_CHIP_P5)) {
                /* clear all RSS setting before free vnic ctx */
                bnxt_hwrm_clear_vnic_rss(bp);
                bnxt_hwrm_vnic_ctx_free(bp);
-               /* before free the vnic, undo the vnic tpa settings */
-               if (bp->flags & BNXT_FLAG_TPA)
-                       bnxt_set_tpa(bp, false);
-               bnxt_hwrm_vnic_free(bp);
        }
+       /* before free the vnic, undo the vnic tpa settings */
+       if (bp->flags & BNXT_FLAG_TPA)
+               bnxt_set_tpa(bp, false);
+       bnxt_hwrm_vnic_free(bp);
+       if (bp->flags & BNXT_FLAG_CHIP_P5)
+               bnxt_hwrm_vnic_ctx_free(bp);
+}
+
+static void bnxt_hwrm_resource_free(struct bnxt *bp, bool close_path,
+                                   bool irq_re_init)
+{
+       bnxt_clear_vnic(bp);
        bnxt_hwrm_ring_free(bp, close_path);
        bnxt_hwrm_ring_grp_free(bp);
        if (irq_re_init) {
index 549c90d3e465f2fd4f7eb494cee47373b953aaf5..c05d663212b20519a89f18d9d9429d897ac99bdf 100644 (file)
@@ -98,10 +98,13 @@ static int bnxt_hwrm_nvm_req(struct bnxt *bp, u32 param_id, void *msg,
        if (idx)
                req->dimensions = cpu_to_le16(1);
 
-       if (req->req_type == cpu_to_le16(HWRM_NVM_SET_VARIABLE))
+       if (req->req_type == cpu_to_le16(HWRM_NVM_SET_VARIABLE)) {
                memcpy(data_addr, buf, bytesize);
-
-       rc = hwrm_send_message(bp, msg, msg_len, HWRM_CMD_TIMEOUT);
+               rc = hwrm_send_message(bp, msg, msg_len, HWRM_CMD_TIMEOUT);
+       } else {
+               rc = hwrm_send_message_silent(bp, msg, msg_len,
+                                             HWRM_CMD_TIMEOUT);
+       }
        if (!rc && req->req_type == cpu_to_le16(HWRM_NVM_GET_VARIABLE))
                memcpy(buf, data_addr, bytesize);
 
index c7ee63d6967983d77087a9dcdda2638b683afcf1..8445a0cce849c0c8781a14dc5f11874cba1a53a5 100644 (file)
@@ -2016,21 +2016,19 @@ static int bnxt_flash_package_from_file(struct net_device *dev,
        mutex_lock(&bp->hwrm_cmd_lock);
        hwrm_err = _hwrm_send_message(bp, &install, sizeof(install),
                                      INSTALL_PACKAGE_TIMEOUT);
-       if (hwrm_err)
-               goto flash_pkg_exit;
-
-       if (resp->error_code) {
+       if (hwrm_err) {
                u8 error_code = ((struct hwrm_err_output *)resp)->cmd_err;
 
-               if (error_code == NVM_INSTALL_UPDATE_CMD_ERR_CODE_FRAG_ERR) {
+               if (resp->error_code && error_code ==
+                   NVM_INSTALL_UPDATE_CMD_ERR_CODE_FRAG_ERR) {
                        install.flags |= cpu_to_le16(
                               NVM_INSTALL_UPDATE_REQ_FLAGS_ALLOWED_TO_DEFRAG);
                        hwrm_err = _hwrm_send_message(bp, &install,
                                                      sizeof(install),
                                                      INSTALL_PACKAGE_TIMEOUT);
-                       if (hwrm_err)
-                               goto flash_pkg_exit;
                }
+               if (hwrm_err)
+                       goto flash_pkg_exit;
        }
 
        if (resp->result) {
index 6fe4a7174271b8286cac810b94e5fa8b95c1a9b5..dd621f6bd1271c8c594185b5a82b8e892b3e6576 100644 (file)
@@ -1236,7 +1236,7 @@ static int __bnxt_tc_del_flow(struct bnxt *bp,
 static void bnxt_tc_set_flow_dir(struct bnxt *bp, struct bnxt_tc_flow *flow,
                                 u16 src_fid)
 {
-       flow->dir = (bp->pf.fw_fid == src_fid) ? BNXT_DIR_RX : BNXT_DIR_TX;
+       flow->l2_key.dir = (bp->pf.fw_fid == src_fid) ? BNXT_DIR_RX : BNXT_DIR_TX;
 }
 
 static void bnxt_tc_set_src_fid(struct bnxt *bp, struct bnxt_tc_flow *flow,
@@ -1285,9 +1285,7 @@ static int bnxt_tc_add_flow(struct bnxt *bp, u16 src_fid,
                goto free_node;
 
        bnxt_tc_set_src_fid(bp, flow, src_fid);
-
-       if (bp->fw_cap & BNXT_FW_CAP_OVS_64BIT_HANDLE)
-               bnxt_tc_set_flow_dir(bp, flow, src_fid);
+       bnxt_tc_set_flow_dir(bp, flow, flow->src_fid);
 
        if (!bnxt_tc_can_offload(bp, flow)) {
                rc = -EOPNOTSUPP;
@@ -1407,7 +1405,7 @@ static void bnxt_fill_cfa_stats_req(struct bnxt *bp,
                 * 2. 15th bit of flow_handle must specify the flow
                 *    direction (TX/RX).
                 */
-               if (flow_node->flow.dir == BNXT_DIR_RX)
+               if (flow_node->flow.l2_key.dir == BNXT_DIR_RX)
                        handle = CFA_FLOW_INFO_REQ_FLOW_HANDLE_DIR_RX |
                                 CFA_FLOW_INFO_REQ_FLOW_HANDLE_MAX_MASK;
                else
index ffec57d1a5ecf2830e191c64bbd270905da209e7..4f05305052f2f27905646188a2d3047683ab419f 100644 (file)
@@ -23,6 +23,9 @@ struct bnxt_tc_l2_key {
        __be16          inner_vlan_tci;
        __be16          ether_type;
        u8              num_vlans;
+       u8              dir;
+#define BNXT_DIR_RX    1
+#define BNXT_DIR_TX    0
 };
 
 struct bnxt_tc_l3_key {
@@ -98,9 +101,6 @@ struct bnxt_tc_flow {
 
        /* flow applicable to pkts ingressing on this fid */
        u16                             src_fid;
-       u8                              dir;
-#define BNXT_DIR_RX    1
-#define BNXT_DIR_TX    0
        struct bnxt_tc_l2_key           l2_key;
        struct bnxt_tc_l2_key           l2_mask;
        struct bnxt_tc_l3_key           l3_key;
index 73632b84374985cffdba907ad605499a6d71d420..b821c9e1604cff9c9b6ea412615140f293d5ee68 100644 (file)
@@ -10,7 +10,7 @@
 
 #include "cavium_ptp.h"
 
-#define DRV_NAME       "Cavium PTP Driver"
+#define DRV_NAME "cavium_ptp"
 
 #define PCI_DEVICE_ID_CAVIUM_PTP       0xA00C
 #define PCI_DEVICE_ID_CAVIUM_RST       0xA00E
index 032224178b647e004dbf509594dbc249822d6806..6dd65f9b347cbc4573434385daaf5ad6e17e8be4 100644 (file)
@@ -237,8 +237,10 @@ int octeon_setup_iq(struct octeon_device *oct,
        }
 
        oct->num_iqs++;
-       if (oct->fn_list.enable_io_queues(oct))
+       if (oct->fn_list.enable_io_queues(oct)) {
+               octeon_delete_instr_queue(oct, iq_no);
                return 1;
+       }
 
        return 0;
 }
index 02959035ed3f21287a3673f93c55f0e76b549de1..d692251ee252c2e98bb46423002acda19829bf8f 100644 (file)
@@ -3236,8 +3236,10 @@ static ssize_t blocked_fl_write(struct file *filp, const char __user *ubuf,
                return -ENOMEM;
 
        err = bitmap_parse_user(ubuf, count, t, adap->sge.egr_sz);
-       if (err)
+       if (err) {
+               kvfree(t);
                return err;
+       }
 
        bitmap_copy(adap->sge.blocked_fl, t, adap->sge.egr_sz);
        kvfree(t);
index 133acca0bf31b448ac0c3f51594dbaef65ed3704..092da2d90026fab2e455f0ba9831ad2788042a74 100644 (file)
@@ -167,7 +167,7 @@ struct nps_enet_priv {
 };
 
 /**
- * nps_reg_set - Sets ENET register with provided value.
+ * nps_enet_reg_set - Sets ENET register with provided value.
  * @priv:       Pointer to EZchip ENET private data structure.
  * @reg:        Register offset from base address.
  * @value:      Value to set in register.
@@ -179,7 +179,7 @@ static inline void nps_enet_reg_set(struct nps_enet_priv *priv,
 }
 
 /**
- * nps_reg_get - Gets value of specified ENET register.
+ * nps_enet_reg_get - Gets value of specified ENET register.
  * @priv:       Pointer to EZchip ENET private data structure.
  * @reg:        Register offset from base address.
  *
index d654c234aaf75364416d3a1eadfa4fb8fa6924ba..c5be4ebd84373ec9ff8ade34b4bae3031e937652 100644 (file)
@@ -1605,7 +1605,7 @@ static int ibmveth_probe(struct vio_dev *dev, const struct vio_device_id *id)
        struct net_device *netdev;
        struct ibmveth_adapter *adapter;
        unsigned char *mac_addr_p;
-       unsigned int *mcastFilterSize_p;
+       __be32 *mcastFilterSize_p;
        long ret;
        unsigned long ret_attr;
 
@@ -1627,8 +1627,9 @@ static int ibmveth_probe(struct vio_dev *dev, const struct vio_device_id *id)
                return -EINVAL;
        }
 
-       mcastFilterSize_p = (unsigned int *)vio_get_attribute(dev,
-                                               VETH_MCAST_FILTER_SIZE, NULL);
+       mcastFilterSize_p = (__be32 *)vio_get_attribute(dev,
+                                                       VETH_MCAST_FILTER_SIZE,
+                                                       NULL);
        if (!mcastFilterSize_p) {
                dev_err(&dev->dev, "Can't find VETH_MCAST_FILTER_SIZE "
                        "attribute\n");
@@ -1645,7 +1646,7 @@ static int ibmveth_probe(struct vio_dev *dev, const struct vio_device_id *id)
 
        adapter->vdev = dev;
        adapter->netdev = netdev;
-       adapter->mcastFilterSize = *mcastFilterSize_p;
+       adapter->mcastFilterSize = be32_to_cpu(*mcastFilterSize_p);
        adapter->pool_config = 0;
 
        netif_napi_add(netdev, &adapter->napi, ibmveth_poll, 16);
index 3da6800732656477bd5d932373dde23d1b4dde9c..cebd20f3128d4a6c6344c94b80496875e091d8d7 100644 (file)
@@ -1568,6 +1568,8 @@ static netdev_tx_t ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)
                lpar_rc = send_subcrq_indirect(adapter, handle_array[queue_num],
                                               (u64)tx_buff->indir_dma,
                                               (u64)num_entries);
+               dma_unmap_single(dev, tx_buff->indir_dma,
+                                sizeof(tx_buff->indir_arr), DMA_TO_DEVICE);
        } else {
                tx_buff->num_entries = num_entries;
                lpar_rc = send_subcrq(adapter, handle_array[queue_num],
@@ -2788,7 +2790,6 @@ static int ibmvnic_complete_tx(struct ibmvnic_adapter *adapter,
        union sub_crq *next;
        int index;
        int i, j;
-       u8 *first;
 
 restart_loop:
        while (pending_scrq(adapter, scrq)) {
@@ -2818,14 +2819,6 @@ restart_loop:
 
                                txbuff->data_dma[j] = 0;
                        }
-                       /* if sub_crq was sent indirectly */
-                       first = &txbuff->indir_arr[0].generic.first;
-                       if (*first == IBMVNIC_CRQ_CMD) {
-                               dma_unmap_single(dev, txbuff->indir_dma,
-                                                sizeof(txbuff->indir_arr),
-                                                DMA_TO_DEVICE);
-                               *first = 0;
-                       }
 
                        if (txbuff->last_frag) {
                                dev_kfree_skb_any(txbuff->skb);
index cbaf712d6529bf0e1d20289c8d0d4a0466b79623..7882148abb4320ccf3a979b565fa93990366f991 100644 (file)
@@ -7897,11 +7897,8 @@ static void ixgbe_service_task(struct work_struct *work)
                return;
        }
        if (ixgbe_check_fw_error(adapter)) {
-               if (!test_bit(__IXGBE_DOWN, &adapter->state)) {
-                       rtnl_lock();
+               if (!test_bit(__IXGBE_DOWN, &adapter->state))
                        unregister_netdev(adapter->netdev);
-                       rtnl_unlock();
-               }
                ixgbe_service_event_complete(adapter);
                return;
        }
index 6c01314e87b09716ca076cbe4a91621b9e474fba..db3552f2d0877e37ce8dcf215d4c273e91c2326c 100644 (file)
@@ -1187,7 +1187,7 @@ int mlx4_en_config_rss_steer(struct mlx4_en_priv *priv)
        err = mlx4_qp_alloc(mdev->dev, priv->base_qpn, rss_map->indir_qp);
        if (err) {
                en_err(priv, "Failed to allocate RSS indirection QP\n");
-               goto rss_err;
+               goto qp_alloc_err;
        }
 
        rss_map->indir_qp->event = mlx4_en_sqp_event;
@@ -1241,6 +1241,7 @@ indir_err:
                       MLX4_QP_STATE_RST, NULL, 0, 0, rss_map->indir_qp);
        mlx4_qp_remove(mdev->dev, rss_map->indir_qp);
        mlx4_qp_free(mdev->dev, rss_map->indir_qp);
+qp_alloc_err:
        kfree(rss_map->indir_qp);
        rss_map->indir_qp = NULL;
 rss_err:
index ce1be2a84231a775c1f6496b07b94ec10b684f97..65bec19a438f15c5db9f0e0d28bd3ac53a7a0c83 100644 (file)
@@ -184,8 +184,13 @@ static inline int mlx5e_get_max_num_channels(struct mlx5_core_dev *mdev)
 
 struct mlx5e_tx_wqe {
        struct mlx5_wqe_ctrl_seg ctrl;
-       struct mlx5_wqe_eth_seg  eth;
-       struct mlx5_wqe_data_seg data[0];
+       union {
+               struct {
+                       struct mlx5_wqe_eth_seg  eth;
+                       struct mlx5_wqe_data_seg data[0];
+               };
+               u8 tls_progress_params_ctx[0];
+       };
 };
 
 struct mlx5e_rx_wqe_ll {
@@ -1100,6 +1105,8 @@ u32 mlx5e_ethtool_get_rxfh_key_size(struct mlx5e_priv *priv);
 u32 mlx5e_ethtool_get_rxfh_indir_size(struct mlx5e_priv *priv);
 int mlx5e_ethtool_get_ts_info(struct mlx5e_priv *priv,
                              struct ethtool_ts_info *info);
+int mlx5e_ethtool_flash_device(struct mlx5e_priv *priv,
+                              struct ethtool_flash *flash);
 void mlx5e_ethtool_get_pauseparam(struct mlx5e_priv *priv,
                                  struct ethtool_pauseparam *pauseparam);
 int mlx5e_ethtool_set_pauseparam(struct mlx5e_priv *priv,
index f3d98748b2117575ad64c83b2bb962ec7a718786..c7f86453c63843c619d6fdad7d078c0ec2acacd3 100644 (file)
@@ -76,26 +76,21 @@ static int mlx5e_tx_reporter_err_cqe_recover(struct mlx5e_txqsq *sq)
        u8 state;
        int err;
 
-       if (!test_bit(MLX5E_SQ_STATE_RECOVERING, &sq->state))
-               return 0;
-
        err = mlx5_core_query_sq_state(mdev, sq->sqn, &state);
        if (err) {
                netdev_err(dev, "Failed to query SQ 0x%x state. err = %d\n",
                           sq->sqn, err);
-               return err;
+               goto out;
        }
 
-       if (state != MLX5_SQC_STATE_ERR) {
-               netdev_err(dev, "SQ 0x%x not in ERROR state\n", sq->sqn);
-               return -EINVAL;
-       }
+       if (state != MLX5_SQC_STATE_ERR)
+               goto out;
 
        mlx5e_tx_disable_queue(sq->txq);
 
        err = mlx5e_wait_for_sq_flush(sq);
        if (err)
-               return err;
+               goto out;
 
        /* At this point, no new packets will arrive from the stack as TXQ is
         * marked with QUEUE_STATE_DRV_XOFF. In addition, NAPI cleared all
@@ -104,13 +99,17 @@ static int mlx5e_tx_reporter_err_cqe_recover(struct mlx5e_txqsq *sq)
 
        err = mlx5e_sq_to_ready(sq, state);
        if (err)
-               return err;
+               goto out;
 
        mlx5e_reset_txqsq_cc_pc(sq);
        sq->stats->recover++;
+       clear_bit(MLX5E_SQ_STATE_RECOVERING, &sq->state);
        mlx5e_activate_txqsq(sq);
 
        return 0;
+out:
+       clear_bit(MLX5E_SQ_STATE_RECOVERING, &sq->state);
+       return err;
 }
 
 static int mlx5_tx_health_report(struct devlink_health_reporter *tx_reporter,
index aaffa6f68dc01c161999896175ea21661be33d81..7f78c004d12f767b2d8f78b281261bebc9bc3557 100644 (file)
@@ -143,7 +143,10 @@ void mlx5e_activate_xsk(struct mlx5e_channel *c)
 {
        set_bit(MLX5E_RQ_STATE_ENABLED, &c->xskrq.state);
        /* TX queue is created active. */
+
+       spin_lock(&c->xskicosq_lock);
        mlx5e_trigger_irq(&c->xskicosq);
+       spin_unlock(&c->xskicosq_lock);
 }
 
 void mlx5e_deactivate_xsk(struct mlx5e_channel *c)
index 407da83474efa08a6c73e74fdebbe58503ff3e3b..b7298f9ee3d3f7d7a2adcb5cd2895d5ab2a0d78f 100644 (file)
 #include "accel/tls.h"
 
 #define MLX5E_KTLS_STATIC_UMR_WQE_SZ \
-       (sizeof(struct mlx5e_umr_wqe) + MLX5_ST_SZ_BYTES(tls_static_params))
+       (offsetof(struct mlx5e_umr_wqe, tls_static_params_ctx) + \
+        MLX5_ST_SZ_BYTES(tls_static_params))
 #define MLX5E_KTLS_STATIC_WQEBBS \
        (DIV_ROUND_UP(MLX5E_KTLS_STATIC_UMR_WQE_SZ, MLX5_SEND_WQE_BB))
 
 #define MLX5E_KTLS_PROGRESS_WQE_SZ \
-       (sizeof(struct mlx5e_tx_wqe) + MLX5_ST_SZ_BYTES(tls_progress_params))
+       (offsetof(struct mlx5e_tx_wqe, tls_progress_params_ctx) + \
+        MLX5_ST_SZ_BYTES(tls_progress_params))
 #define MLX5E_KTLS_PROGRESS_WQEBBS \
        (DIV_ROUND_UP(MLX5E_KTLS_PROGRESS_WQE_SZ, MLX5_SEND_WQE_BB))
 #define MLX5E_KTLS_MAX_DUMP_WQEBBS 2
index 3766545ce2599699a59deb89d2d59de6e8335e0b..8b93101e1a09b633bb4f84c932ee3b6207f5895d 100644 (file)
@@ -69,7 +69,7 @@ build_static_params(struct mlx5e_umr_wqe *wqe, u16 pc, u32 sqn,
        cseg->qpn_ds           = cpu_to_be32((sqn << MLX5_WQE_CTRL_QPN_SHIFT) |
                                             STATIC_PARAMS_DS_CNT);
        cseg->fm_ce_se         = fence ? MLX5_FENCE_MODE_INITIATOR_SMALL : 0;
-       cseg->imm              = cpu_to_be32(priv_tx->tisn);
+       cseg->tisn             = cpu_to_be32(priv_tx->tisn << 8);
 
        ucseg->flags = MLX5_UMR_INLINE;
        ucseg->bsf_octowords = cpu_to_be16(MLX5_ST_SZ_BYTES(tls_static_params) / 16);
@@ -80,7 +80,7 @@ build_static_params(struct mlx5e_umr_wqe *wqe, u16 pc, u32 sqn,
 static void
 fill_progress_params_ctx(void *ctx, struct mlx5e_ktls_offload_context_tx *priv_tx)
 {
-       MLX5_SET(tls_progress_params, ctx, pd, priv_tx->tisn);
+       MLX5_SET(tls_progress_params, ctx, tisn, priv_tx->tisn);
        MLX5_SET(tls_progress_params, ctx, record_tracker_state,
                 MLX5E_TLS_PROGRESS_PARAMS_RECORD_TRACKER_STATE_START);
        MLX5_SET(tls_progress_params, ctx, auth_state,
@@ -104,7 +104,7 @@ build_progress_params(struct mlx5e_tx_wqe *wqe, u16 pc, u32 sqn,
                                             PROGRESS_PARAMS_DS_CNT);
        cseg->fm_ce_se         = fence ? MLX5_FENCE_MODE_INITIATOR_SMALL : 0;
 
-       fill_progress_params_ctx(wqe->data, priv_tx);
+       fill_progress_params_ctx(wqe->tls_progress_params_ctx, priv_tx);
 }
 
 static void tx_fill_wi(struct mlx5e_txqsq *sq,
@@ -278,7 +278,7 @@ tx_post_resync_dump(struct mlx5e_txqsq *sq, struct sk_buff *skb,
 
        cseg->opmod_idx_opcode = cpu_to_be32((sq->pc << 8)  | MLX5_OPCODE_DUMP);
        cseg->qpn_ds           = cpu_to_be32((sq->sqn << 8) | ds_cnt);
-       cseg->imm              = cpu_to_be32(tisn);
+       cseg->tisn             = cpu_to_be32(tisn << 8);
        cseg->fm_ce_se         = first ? MLX5_FENCE_MODE_INITIATOR_SMALL : 0;
 
        eseg->inline_hdr.sz = cpu_to_be16(ihs);
@@ -434,7 +434,7 @@ struct sk_buff *mlx5e_ktls_handle_tx_skb(struct net_device *netdev,
        priv_tx->expected_seq = seq + datalen;
 
        cseg = &(*wqe)->ctrl;
-       cseg->imm = cpu_to_be32(priv_tx->tisn);
+       cseg->tisn = cpu_to_be32(priv_tx->tisn << 8);
 
        stats->tls_encrypted_packets += skb_is_gso(skb) ? skb_shinfo(skb)->gso_segs : 1;
        stats->tls_encrypted_bytes   += datalen;
index 8657e0f26995b442545dabd3b7b8d5b299b5a380..2c75b2752f58de0e7d0c3e9760736d7ee8035211 100644 (file)
@@ -437,12 +437,6 @@ arfs_hash_bucket(struct arfs_table *arfs_t, __be16 src_port,
        return &arfs_t->rules_hash[bucket_idx];
 }
 
-static u8 arfs_get_ip_proto(const struct sk_buff *skb)
-{
-       return (skb->protocol == htons(ETH_P_IP)) ?
-               ip_hdr(skb)->protocol : ipv6_hdr(skb)->nexthdr;
-}
-
 static struct arfs_table *arfs_get_table(struct mlx5e_arfs_tables *arfs,
                                         u8 ip_proto, __be16 etype)
 {
@@ -602,31 +596,9 @@ out:
        arfs_may_expire_flow(priv);
 }
 
-/* return L4 destination port from ip4/6 packets */
-static __be16 arfs_get_dst_port(const struct sk_buff *skb)
-{
-       char *transport_header;
-
-       transport_header = skb_transport_header(skb);
-       if (arfs_get_ip_proto(skb) == IPPROTO_TCP)
-               return ((struct tcphdr *)transport_header)->dest;
-       return ((struct udphdr *)transport_header)->dest;
-}
-
-/* return L4 source port from ip4/6 packets */
-static __be16 arfs_get_src_port(const struct sk_buff *skb)
-{
-       char *transport_header;
-
-       transport_header = skb_transport_header(skb);
-       if (arfs_get_ip_proto(skb) == IPPROTO_TCP)
-               return ((struct tcphdr *)transport_header)->source;
-       return ((struct udphdr *)transport_header)->source;
-}
-
 static struct arfs_rule *arfs_alloc_rule(struct mlx5e_priv *priv,
                                         struct arfs_table *arfs_t,
-                                        const struct sk_buff *skb,
+                                        const struct flow_keys *fk,
                                         u16 rxq, u32 flow_id)
 {
        struct arfs_rule *rule;
@@ -641,19 +613,19 @@ static struct arfs_rule *arfs_alloc_rule(struct mlx5e_priv *priv,
        INIT_WORK(&rule->arfs_work, arfs_handle_work);
 
        tuple = &rule->tuple;
-       tuple->etype = skb->protocol;
+       tuple->etype = fk->basic.n_proto;
+       tuple->ip_proto = fk->basic.ip_proto;
        if (tuple->etype == htons(ETH_P_IP)) {
-               tuple->src_ipv4 = ip_hdr(skb)->saddr;
-               tuple->dst_ipv4 = ip_hdr(skb)->daddr;
+               tuple->src_ipv4 = fk->addrs.v4addrs.src;
+               tuple->dst_ipv4 = fk->addrs.v4addrs.dst;
        } else {
-               memcpy(&tuple->src_ipv6, &ipv6_hdr(skb)->saddr,
+               memcpy(&tuple->src_ipv6, &fk->addrs.v6addrs.src,
                       sizeof(struct in6_addr));
-               memcpy(&tuple->dst_ipv6, &ipv6_hdr(skb)->daddr,
+               memcpy(&tuple->dst_ipv6, &fk->addrs.v6addrs.dst,
                       sizeof(struct in6_addr));
        }
-       tuple->ip_proto = arfs_get_ip_proto(skb);
-       tuple->src_port = arfs_get_src_port(skb);
-       tuple->dst_port = arfs_get_dst_port(skb);
+       tuple->src_port = fk->ports.src;
+       tuple->dst_port = fk->ports.dst;
 
        rule->flow_id = flow_id;
        rule->filter_id = priv->fs.arfs.last_filter_id++ % RPS_NO_FILTER;
@@ -664,37 +636,33 @@ static struct arfs_rule *arfs_alloc_rule(struct mlx5e_priv *priv,
        return rule;
 }
 
-static bool arfs_cmp_ips(struct arfs_tuple *tuple,
-                        const struct sk_buff *skb)
+static bool arfs_cmp(const struct arfs_tuple *tuple, const struct flow_keys *fk)
 {
-       if (tuple->etype == htons(ETH_P_IP) &&
-           tuple->src_ipv4 == ip_hdr(skb)->saddr &&
-           tuple->dst_ipv4 == ip_hdr(skb)->daddr)
-               return true;
-       if (tuple->etype == htons(ETH_P_IPV6) &&
-           (!memcmp(&tuple->src_ipv6, &ipv6_hdr(skb)->saddr,
-                    sizeof(struct in6_addr))) &&
-           (!memcmp(&tuple->dst_ipv6, &ipv6_hdr(skb)->daddr,
-                    sizeof(struct in6_addr))))
-               return true;
+       if (tuple->src_port != fk->ports.src || tuple->dst_port != fk->ports.dst)
+               return false;
+       if (tuple->etype != fk->basic.n_proto)
+               return false;
+       if (tuple->etype == htons(ETH_P_IP))
+               return tuple->src_ipv4 == fk->addrs.v4addrs.src &&
+                      tuple->dst_ipv4 == fk->addrs.v4addrs.dst;
+       if (tuple->etype == htons(ETH_P_IPV6))
+               return !memcmp(&tuple->src_ipv6, &fk->addrs.v6addrs.src,
+                              sizeof(struct in6_addr)) &&
+                      !memcmp(&tuple->dst_ipv6, &fk->addrs.v6addrs.dst,
+                              sizeof(struct in6_addr));
        return false;
 }
 
 static struct arfs_rule *arfs_find_rule(struct arfs_table *arfs_t,
-                                       const struct sk_buff *skb)
+                                       const struct flow_keys *fk)
 {
        struct arfs_rule *arfs_rule;
        struct hlist_head *head;
-       __be16 src_port = arfs_get_src_port(skb);
-       __be16 dst_port = arfs_get_dst_port(skb);
 
-       head = arfs_hash_bucket(arfs_t, src_port, dst_port);
+       head = arfs_hash_bucket(arfs_t, fk->ports.src, fk->ports.dst);
        hlist_for_each_entry(arfs_rule, head, hlist) {
-               if (arfs_rule->tuple.src_port == src_port &&
-                   arfs_rule->tuple.dst_port == dst_port &&
-                   arfs_cmp_ips(&arfs_rule->tuple, skb)) {
+               if (arfs_cmp(&arfs_rule->tuple, fk))
                        return arfs_rule;
-               }
        }
 
        return NULL;
@@ -707,20 +675,24 @@ int mlx5e_rx_flow_steer(struct net_device *dev, const struct sk_buff *skb,
        struct mlx5e_arfs_tables *arfs = &priv->fs.arfs;
        struct arfs_table *arfs_t;
        struct arfs_rule *arfs_rule;
+       struct flow_keys fk;
+
+       if (!skb_flow_dissect_flow_keys(skb, &fk, 0))
+               return -EPROTONOSUPPORT;
 
-       if (skb->protocol != htons(ETH_P_IP) &&
-           skb->protocol != htons(ETH_P_IPV6))
+       if (fk.basic.n_proto != htons(ETH_P_IP) &&
+           fk.basic.n_proto != htons(ETH_P_IPV6))
                return -EPROTONOSUPPORT;
 
        if (skb->encapsulation)
                return -EPROTONOSUPPORT;
 
-       arfs_t = arfs_get_table(arfs, arfs_get_ip_proto(skb), skb->protocol);
+       arfs_t = arfs_get_table(arfs, fk.basic.ip_proto, fk.basic.n_proto);
        if (!arfs_t)
                return -EPROTONOSUPPORT;
 
        spin_lock_bh(&arfs->arfs_lock);
-       arfs_rule = arfs_find_rule(arfs_t, skb);
+       arfs_rule = arfs_find_rule(arfs_t, &fk);
        if (arfs_rule) {
                if (arfs_rule->rxq == rxq_index) {
                        spin_unlock_bh(&arfs->arfs_lock);
@@ -728,8 +700,7 @@ int mlx5e_rx_flow_steer(struct net_device *dev, const struct sk_buff *skb,
                }
                arfs_rule->rxq = rxq_index;
        } else {
-               arfs_rule = arfs_alloc_rule(priv, arfs_t, skb,
-                                           rxq_index, flow_id);
+               arfs_rule = arfs_alloc_rule(priv, arfs_t, &fk, rxq_index, flow_id);
                if (!arfs_rule) {
                        spin_unlock_bh(&arfs->arfs_lock);
                        return -ENOMEM;
index 03bed714bac3f919675517b5bb759a1c7e9e2d6a..20e628c907e53a3020c211575e059ab800c22e50 100644 (file)
@@ -1081,6 +1081,14 @@ int mlx5e_ethtool_set_link_ksettings(struct mlx5e_priv *priv,
        link_modes = autoneg == AUTONEG_ENABLE ? ethtool2ptys_adver_func(adver) :
                mlx5e_port_speed2linkmodes(mdev, speed, !ext);
 
+       if ((link_modes & MLX5E_PROT_MASK(MLX5E_56GBASE_R4)) &&
+           autoneg != AUTONEG_ENABLE) {
+               netdev_err(priv->netdev, "%s: 56G link speed requires autoneg enabled\n",
+                          __func__);
+               err = -EINVAL;
+               goto out;
+       }
+
        link_modes = link_modes & eproto.cap;
        if (!link_modes) {
                netdev_err(priv->netdev, "%s: Not supported link mode(s) requested",
@@ -1338,6 +1346,9 @@ int mlx5e_ethtool_set_pauseparam(struct mlx5e_priv *priv,
        struct mlx5_core_dev *mdev = priv->mdev;
        int err;
 
+       if (!MLX5_CAP_GEN(mdev, vport_group_manager))
+               return -EOPNOTSUPP;
+
        if (pauseparam->autoneg)
                return -EINVAL;
 
@@ -1679,6 +1690,40 @@ static int mlx5e_get_module_eeprom(struct net_device *netdev,
        return 0;
 }
 
+int mlx5e_ethtool_flash_device(struct mlx5e_priv *priv,
+                              struct ethtool_flash *flash)
+{
+       struct mlx5_core_dev *mdev = priv->mdev;
+       struct net_device *dev = priv->netdev;
+       const struct firmware *fw;
+       int err;
+
+       if (flash->region != ETHTOOL_FLASH_ALL_REGIONS)
+               return -EOPNOTSUPP;
+
+       err = request_firmware_direct(&fw, flash->data, &dev->dev);
+       if (err)
+               return err;
+
+       dev_hold(dev);
+       rtnl_unlock();
+
+       err = mlx5_firmware_flash(mdev, fw, NULL);
+       release_firmware(fw);
+
+       rtnl_lock();
+       dev_put(dev);
+       return err;
+}
+
+static int mlx5e_flash_device(struct net_device *dev,
+                             struct ethtool_flash *flash)
+{
+       struct mlx5e_priv *priv = netdev_priv(dev);
+
+       return mlx5e_ethtool_flash_device(priv, flash);
+}
+
 static int set_pflag_cqe_based_moder(struct net_device *netdev, bool enable,
                                     bool is_rx_cq)
 {
@@ -1961,6 +2006,7 @@ const struct ethtool_ops mlx5e_ethtool_ops = {
        .set_wol           = mlx5e_set_wol,
        .get_module_info   = mlx5e_get_module_info,
        .get_module_eeprom = mlx5e_get_module_eeprom,
+       .flash_device      = mlx5e_flash_device,
        .get_priv_flags    = mlx5e_get_priv_flags,
        .set_priv_flags    = mlx5e_set_priv_flags,
        .self_test         = mlx5e_self_test,
index 6c712c5be4d81dec3ae3a58f5fb8d11c21456ebd..9d5f6e56188f825bbbe605f1bfb3af09604d5e42 100644 (file)
@@ -1321,7 +1321,6 @@ err_free_txqsq:
 void mlx5e_activate_txqsq(struct mlx5e_txqsq *sq)
 {
        sq->txq = netdev_get_tx_queue(sq->channel->netdev, sq->txq_ix);
-       clear_bit(MLX5E_SQ_STATE_RECOVERING, &sq->state);
        set_bit(MLX5E_SQ_STATE_ENABLED, &sq->state);
        netdev_tx_reset_queue(sq->txq);
        netif_tx_start_queue(sq->txq);
index 7ecfc53cf5f6503df89dfc1983ed0b2290470247..00b2d4a86159f142e491278769fe1679ce5a2d20 100644 (file)
@@ -1480,7 +1480,7 @@ static int __parse_cls_flower(struct mlx5e_priv *priv,
                              struct mlx5_flow_spec *spec,
                              struct flow_cls_offload *f,
                              struct net_device *filter_dev,
-                             u8 *match_level, u8 *tunnel_match_level)
+                             u8 *inner_match_level, u8 *outer_match_level)
 {
        struct netlink_ext_ack *extack = f->common.extack;
        void *headers_c = MLX5_ADDR_OF(fte_match_param, spec->match_criteria,
@@ -1495,8 +1495,9 @@ static int __parse_cls_flower(struct mlx5e_priv *priv,
        struct flow_dissector *dissector = rule->match.dissector;
        u16 addr_type = 0;
        u8 ip_proto = 0;
+       u8 *match_level;
 
-       *match_level = MLX5_MATCH_NONE;
+       match_level = outer_match_level;
 
        if (dissector->used_keys &
            ~(BIT(FLOW_DISSECTOR_KEY_META) |
@@ -1524,12 +1525,14 @@ static int __parse_cls_flower(struct mlx5e_priv *priv,
        }
 
        if (mlx5e_get_tc_tun(filter_dev)) {
-               if (parse_tunnel_attr(priv, spec, f, filter_dev, tunnel_match_level))
+               if (parse_tunnel_attr(priv, spec, f, filter_dev,
+                                     outer_match_level))
                        return -EOPNOTSUPP;
 
-               /* In decap flow, header pointers should point to the inner
+               /* At this point, header pointers should point to the inner
                 * headers, outer header were already set by parse_tunnel_attr
                 */
+               match_level = inner_match_level;
                headers_c = get_match_headers_criteria(MLX5_FLOW_CONTEXT_ACTION_DECAP,
                                                       spec);
                headers_v = get_match_headers_value(MLX5_FLOW_CONTEXT_ACTION_DECAP,
@@ -1831,35 +1834,41 @@ static int parse_cls_flower(struct mlx5e_priv *priv,
                            struct flow_cls_offload *f,
                            struct net_device *filter_dev)
 {
+       u8 inner_match_level, outer_match_level, non_tunnel_match_level;
        struct netlink_ext_ack *extack = f->common.extack;
        struct mlx5_core_dev *dev = priv->mdev;
        struct mlx5_eswitch *esw = dev->priv.eswitch;
        struct mlx5e_rep_priv *rpriv = priv->ppriv;
-       u8 match_level, tunnel_match_level = MLX5_MATCH_NONE;
        struct mlx5_eswitch_rep *rep;
        int err;
 
-       err = __parse_cls_flower(priv, spec, f, filter_dev, &match_level, &tunnel_match_level);
+       inner_match_level = MLX5_MATCH_NONE;
+       outer_match_level = MLX5_MATCH_NONE;
+
+       err = __parse_cls_flower(priv, spec, f, filter_dev, &inner_match_level,
+                                &outer_match_level);
+       non_tunnel_match_level = (inner_match_level == MLX5_MATCH_NONE) ?
+                                outer_match_level : inner_match_level;
 
        if (!err && (flow->flags & MLX5E_TC_FLOW_ESWITCH)) {
                rep = rpriv->rep;
                if (rep->vport != MLX5_VPORT_UPLINK &&
                    (esw->offloads.inline_mode != MLX5_INLINE_MODE_NONE &&
-                   esw->offloads.inline_mode < match_level)) {
+                   esw->offloads.inline_mode < non_tunnel_match_level)) {
                        NL_SET_ERR_MSG_MOD(extack,
                                           "Flow is not offloaded due to min inline setting");
                        netdev_warn(priv->netdev,
                                    "Flow is not offloaded due to min inline setting, required %d actual %d\n",
-                                   match_level, esw->offloads.inline_mode);
+                                   non_tunnel_match_level, esw->offloads.inline_mode);
                        return -EOPNOTSUPP;
                }
        }
 
        if (flow->flags & MLX5E_TC_FLOW_ESWITCH) {
-               flow->esw_attr->match_level = match_level;
-               flow->esw_attr->tunnel_match_level = tunnel_match_level;
+               flow->esw_attr->inner_match_level = inner_match_level;
+               flow->esw_attr->outer_match_level = outer_match_level;
        } else {
-               flow->nic_attr->match_level = match_level;
+               flow->nic_attr->match_level = non_tunnel_match_level;
        }
 
        return err;
@@ -3158,7 +3167,7 @@ mlx5e_flow_esw_attr_init(struct mlx5_esw_flow_attr *esw_attr,
 
        esw_attr->parse_attr = parse_attr;
        esw_attr->chain = f->common.chain_index;
-       esw_attr->prio = TC_H_MAJ(f->common.prio) >> 16;
+       esw_attr->prio = f->common.prio;
 
        esw_attr->in_rep = in_rep;
        esw_attr->in_mdev = in_mdev;
index a38e8a3c7c9a3b71b6a51c9f440b25878508340f..04685dbb280cfad006007a070ac0d2414a5fd894 100644 (file)
@@ -377,8 +377,8 @@ struct mlx5_esw_flow_attr {
                struct mlx5_termtbl_handle *termtbl;
        } dests[MLX5_MAX_FLOW_FWD_VPORTS];
        u32     mod_hdr_id;
-       u8      match_level;
-       u8      tunnel_match_level;
+       u8      inner_match_level;
+       u8      outer_match_level;
        struct mlx5_fc *counter;
        u32     chain;
        u16     prio;
index 089ae4d48a82dda15e47c49530f9a4e513577acb..0323fd078271bce17cff6a8c963cf803b7437fda 100644 (file)
@@ -207,14 +207,10 @@ mlx5_eswitch_add_offloaded_rule(struct mlx5_eswitch *esw,
 
        mlx5_eswitch_set_rule_source_port(esw, spec, attr);
 
-       if (flow_act.action & MLX5_FLOW_CONTEXT_ACTION_DECAP) {
-               if (attr->tunnel_match_level != MLX5_MATCH_NONE)
-                       spec->match_criteria_enable |= MLX5_MATCH_OUTER_HEADERS;
-               if (attr->match_level != MLX5_MATCH_NONE)
-                       spec->match_criteria_enable |= MLX5_MATCH_INNER_HEADERS;
-       } else if (attr->match_level != MLX5_MATCH_NONE) {
+       if (attr->outer_match_level != MLX5_MATCH_NONE)
                spec->match_criteria_enable |= MLX5_MATCH_OUTER_HEADERS;
-       }
+       if (attr->inner_match_level != MLX5_MATCH_NONE)
+               spec->match_criteria_enable |= MLX5_MATCH_INNER_HEADERS;
 
        if (flow_act.action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR)
                flow_act.modify_id = attr->mod_hdr_id;
@@ -290,7 +286,7 @@ mlx5_eswitch_add_fwd_rule(struct mlx5_eswitch *esw,
        mlx5_eswitch_set_rule_source_port(esw, spec, attr);
 
        spec->match_criteria_enable |= MLX5_MATCH_MISC_PARAMETERS;
-       if (attr->match_level != MLX5_MATCH_NONE)
+       if (attr->outer_match_level != MLX5_MATCH_NONE)
                spec->match_criteria_enable |= MLX5_MATCH_OUTER_HEADERS;
 
        rule = mlx5_add_flow_rules(fast_fdb, spec, &flow_act, dest, i);
index ebd81f6b556e9e6b00e3cf3534a5260a8f01e7ad..90cb50fe17fd95de3a5f295a8cbe60f97cabafa8 100644 (file)
@@ -122,6 +122,14 @@ static int mlx5i_get_ts_info(struct net_device *netdev,
        return mlx5e_ethtool_get_ts_info(priv, info);
 }
 
+static int mlx5i_flash_device(struct net_device *netdev,
+                             struct ethtool_flash *flash)
+{
+       struct mlx5e_priv *priv = mlx5i_epriv(netdev);
+
+       return mlx5e_ethtool_flash_device(priv, flash);
+}
+
 enum mlx5_ptys_width {
        MLX5_PTYS_WIDTH_1X      = 1 << 0,
        MLX5_PTYS_WIDTH_2X      = 1 << 1,
@@ -233,6 +241,7 @@ const struct ethtool_ops mlx5i_ethtool_ops = {
        .get_ethtool_stats  = mlx5i_get_ethtool_stats,
        .get_ringparam      = mlx5i_get_ringparam,
        .set_ringparam      = mlx5i_set_ringparam,
+       .flash_device       = mlx5i_flash_device,
        .get_channels       = mlx5i_get_channels,
        .set_channels       = mlx5i_set_channels,
        .get_coalesce       = mlx5i_get_coalesce,
index ea9ee88491e5d13e120efed9556af2241eec92c6..ea1d4d26ece06a242b86182fe77aff766c76fbf7 100644 (file)
@@ -27,6 +27,7 @@ int mlx5_create_encryption_key(struct mlx5_core_dev *mdev,
        case 128:
                general_obj_key_size =
                        MLX5_GENERAL_OBJECT_TYPE_ENCRYPTION_KEY_KEY_SIZE_128;
+               key_p += sz_bytes;
                break;
        case 256:
                general_obj_key_size =
index e8ac90564dbe5ee36d3206542fa06145b51bfb3b..84a87d0593338845ef6d900d9ae865763729ead4 100644 (file)
@@ -471,7 +471,7 @@ int mlxsw_sp_acl_rulei_commit(struct mlxsw_sp_acl_rule_info *rulei)
 void mlxsw_sp_acl_rulei_priority(struct mlxsw_sp_acl_rule_info *rulei,
                                 unsigned int priority)
 {
-       rulei->priority = priority >> 16;
+       rulei->priority = priority;
 }
 
 void mlxsw_sp_acl_rulei_keymask_u32(struct mlxsw_sp_acl_rule_info *rulei,
index 63b07edd9d8161304793e7321b5c3ea726416a1e..38bb1cfe4e8c566153c138b61babb7b59bc58059 100644 (file)
@@ -29,7 +29,7 @@
 
 struct mlxsw_sp_ptp_state {
        struct mlxsw_sp *mlxsw_sp;
-       struct rhashtable unmatched_ht;
+       struct rhltable unmatched_ht;
        spinlock_t unmatched_lock; /* protects the HT */
        struct delayed_work ht_gc_dw;
        u32 gc_cycle;
@@ -45,7 +45,7 @@ struct mlxsw_sp1_ptp_key {
 
 struct mlxsw_sp1_ptp_unmatched {
        struct mlxsw_sp1_ptp_key key;
-       struct rhash_head ht_node;
+       struct rhlist_head ht_node;
        struct rcu_head rcu;
        struct sk_buff *skb;
        u64 timestamp;
@@ -359,7 +359,7 @@ static int mlxsw_sp_ptp_parse(struct sk_buff *skb,
 /* Returns NULL on successful insertion, a pointer on conflict, or an ERR_PTR on
  * error.
  */
-static struct mlxsw_sp1_ptp_unmatched *
+static int
 mlxsw_sp1_ptp_unmatched_save(struct mlxsw_sp *mlxsw_sp,
                             struct mlxsw_sp1_ptp_key key,
                             struct sk_buff *skb,
@@ -368,41 +368,51 @@ mlxsw_sp1_ptp_unmatched_save(struct mlxsw_sp *mlxsw_sp,
        int cycles = MLXSW_SP1_PTP_HT_GC_TIMEOUT / MLXSW_SP1_PTP_HT_GC_INTERVAL;
        struct mlxsw_sp_ptp_state *ptp_state = mlxsw_sp->ptp_state;
        struct mlxsw_sp1_ptp_unmatched *unmatched;
-       struct mlxsw_sp1_ptp_unmatched *conflict;
+       int err;
 
        unmatched = kzalloc(sizeof(*unmatched), GFP_ATOMIC);
        if (!unmatched)
-               return ERR_PTR(-ENOMEM);
+               return -ENOMEM;
 
        unmatched->key = key;
        unmatched->skb = skb;
        unmatched->timestamp = timestamp;
        unmatched->gc_cycle = mlxsw_sp->ptp_state->gc_cycle + cycles;
 
-       conflict = rhashtable_lookup_get_insert_fast(&ptp_state->unmatched_ht,
-                                           &unmatched->ht_node,
-                                           mlxsw_sp1_ptp_unmatched_ht_params);
-       if (conflict)
+       err = rhltable_insert(&ptp_state->unmatched_ht, &unmatched->ht_node,
+                             mlxsw_sp1_ptp_unmatched_ht_params);
+       if (err)
                kfree(unmatched);
 
-       return conflict;
+       return err;
 }
 
 static struct mlxsw_sp1_ptp_unmatched *
 mlxsw_sp1_ptp_unmatched_lookup(struct mlxsw_sp *mlxsw_sp,
-                              struct mlxsw_sp1_ptp_key key)
+                              struct mlxsw_sp1_ptp_key key, int *p_length)
 {
-       return rhashtable_lookup(&mlxsw_sp->ptp_state->unmatched_ht, &key,
-                                mlxsw_sp1_ptp_unmatched_ht_params);
+       struct mlxsw_sp1_ptp_unmatched *unmatched, *last = NULL;
+       struct rhlist_head *tmp, *list;
+       int length = 0;
+
+       list = rhltable_lookup(&mlxsw_sp->ptp_state->unmatched_ht, &key,
+                              mlxsw_sp1_ptp_unmatched_ht_params);
+       rhl_for_each_entry_rcu(unmatched, tmp, list, ht_node) {
+               last = unmatched;
+               length++;
+       }
+
+       *p_length = length;
+       return last;
 }
 
 static int
 mlxsw_sp1_ptp_unmatched_remove(struct mlxsw_sp *mlxsw_sp,
                               struct mlxsw_sp1_ptp_unmatched *unmatched)
 {
-       return rhashtable_remove_fast(&mlxsw_sp->ptp_state->unmatched_ht,
-                                     &unmatched->ht_node,
-                                     mlxsw_sp1_ptp_unmatched_ht_params);
+       return rhltable_remove(&mlxsw_sp->ptp_state->unmatched_ht,
+                              &unmatched->ht_node,
+                              mlxsw_sp1_ptp_unmatched_ht_params);
 }
 
 /* This function is called in the following scenarios:
@@ -489,75 +499,38 @@ static void mlxsw_sp1_ptp_got_piece(struct mlxsw_sp *mlxsw_sp,
                                    struct mlxsw_sp1_ptp_key key,
                                    struct sk_buff *skb, u64 timestamp)
 {
-       struct mlxsw_sp1_ptp_unmatched *unmatched, *conflict;
+       struct mlxsw_sp1_ptp_unmatched *unmatched;
+       int length;
        int err;
 
        rcu_read_lock();
 
-       unmatched = mlxsw_sp1_ptp_unmatched_lookup(mlxsw_sp, key);
-
        spin_lock(&mlxsw_sp->ptp_state->unmatched_lock);
 
-       if (unmatched) {
-               /* There was an unmatched entry when we looked, but it may have
-                * been removed before we took the lock.
-                */
-               err = mlxsw_sp1_ptp_unmatched_remove(mlxsw_sp, unmatched);
-               if (err)
-                       unmatched = NULL;
-       }
-
-       if (!unmatched) {
-               /* We have no unmatched entry, but one may have been added after
-                * we looked, but before we took the lock.
-                */
-               unmatched = mlxsw_sp1_ptp_unmatched_save(mlxsw_sp, key,
-                                                        skb, timestamp);
-               if (IS_ERR(unmatched)) {
-                       if (skb)
-                               mlxsw_sp1_ptp_packet_finish(mlxsw_sp, skb,
-                                                           key.local_port,
-                                                           key.ingress, NULL);
-                       unmatched = NULL;
-               } else if (unmatched) {
-                       /* Save just told us, under lock, that the entry is
-                        * there, so this has to work.
-                        */
-                       err = mlxsw_sp1_ptp_unmatched_remove(mlxsw_sp,
-                                                            unmatched);
-                       WARN_ON_ONCE(err);
-               }
-       }
-
-       /* If unmatched is non-NULL here, it comes either from the lookup, or
-        * from the save attempt above. In either case the entry was removed
-        * from the hash table. If unmatched is NULL, a new unmatched entry was
-        * added to the hash table, and there was no conflict.
-        */
-
+       unmatched = mlxsw_sp1_ptp_unmatched_lookup(mlxsw_sp, key, &length);
        if (skb && unmatched && unmatched->timestamp) {
                unmatched->skb = skb;
        } else if (timestamp && unmatched && unmatched->skb) {
                unmatched->timestamp = timestamp;
-       } else if (unmatched) {
-               /* unmatched holds an older entry of the same type: either an
-                * skb if we are handling skb, or a timestamp if we are handling
-                * timestamp. We can't match that up, so save what we have.
+       } else {
+               /* Either there is no entry to match, or one that is there is
+                * incompatible.
                 */
-               conflict = mlxsw_sp1_ptp_unmatched_save(mlxsw_sp, key,
-                                                       skb, timestamp);
-               if (IS_ERR(conflict)) {
-                       if (skb)
-                               mlxsw_sp1_ptp_packet_finish(mlxsw_sp, skb,
-                                                           key.local_port,
-                                                           key.ingress, NULL);
-               } else {
-                       /* Above, we removed an object with this key from the
-                        * hash table, under lock, so conflict can not be a
-                        * valid pointer.
-                        */
-                       WARN_ON_ONCE(conflict);
-               }
+               if (length < 100)
+                       err = mlxsw_sp1_ptp_unmatched_save(mlxsw_sp, key,
+                                                          skb, timestamp);
+               else
+                       err = -E2BIG;
+               if (err && skb)
+                       mlxsw_sp1_ptp_packet_finish(mlxsw_sp, skb,
+                                                   key.local_port,
+                                                   key.ingress, NULL);
+               unmatched = NULL;
+       }
+
+       if (unmatched) {
+               err = mlxsw_sp1_ptp_unmatched_remove(mlxsw_sp, unmatched);
+               WARN_ON_ONCE(err);
        }
 
        spin_unlock(&mlxsw_sp->ptp_state->unmatched_lock);
@@ -669,9 +642,8 @@ mlxsw_sp1_ptp_ht_gc_collect(struct mlxsw_sp_ptp_state *ptp_state,
        local_bh_disable();
 
        spin_lock(&ptp_state->unmatched_lock);
-       err = rhashtable_remove_fast(&ptp_state->unmatched_ht,
-                                    &unmatched->ht_node,
-                                    mlxsw_sp1_ptp_unmatched_ht_params);
+       err = rhltable_remove(&ptp_state->unmatched_ht, &unmatched->ht_node,
+                             mlxsw_sp1_ptp_unmatched_ht_params);
        spin_unlock(&ptp_state->unmatched_lock);
 
        if (err)
@@ -702,7 +674,7 @@ static void mlxsw_sp1_ptp_ht_gc(struct work_struct *work)
        ptp_state = container_of(dwork, struct mlxsw_sp_ptp_state, ht_gc_dw);
        gc_cycle = ptp_state->gc_cycle++;
 
-       rhashtable_walk_enter(&ptp_state->unmatched_ht, &iter);
+       rhltable_walk_enter(&ptp_state->unmatched_ht, &iter);
        rhashtable_walk_start(&iter);
        while ((obj = rhashtable_walk_next(&iter))) {
                if (IS_ERR(obj))
@@ -855,8 +827,8 @@ struct mlxsw_sp_ptp_state *mlxsw_sp1_ptp_init(struct mlxsw_sp *mlxsw_sp)
 
        spin_lock_init(&ptp_state->unmatched_lock);
 
-       err = rhashtable_init(&ptp_state->unmatched_ht,
-                             &mlxsw_sp1_ptp_unmatched_ht_params);
+       err = rhltable_init(&ptp_state->unmatched_ht,
+                           &mlxsw_sp1_ptp_unmatched_ht_params);
        if (err)
                goto err_hashtable_init;
 
@@ -891,7 +863,7 @@ err_fifo_clr:
 err_mtptpt1_set:
        mlxsw_sp_ptp_mtptpt_set(mlxsw_sp, MLXSW_REG_MTPTPT_TRAP_ID_PTP0, 0);
 err_mtptpt_set:
-       rhashtable_destroy(&ptp_state->unmatched_ht);
+       rhltable_destroy(&ptp_state->unmatched_ht);
 err_hashtable_init:
        kfree(ptp_state);
        return ERR_PTR(err);
@@ -906,8 +878,8 @@ void mlxsw_sp1_ptp_fini(struct mlxsw_sp_ptp_state *ptp_state)
        mlxsw_sp1_ptp_set_fifo_clr_on_trap(mlxsw_sp, false);
        mlxsw_sp_ptp_mtptpt_set(mlxsw_sp, MLXSW_REG_MTPTPT_TRAP_ID_PTP1, 0);
        mlxsw_sp_ptp_mtptpt_set(mlxsw_sp, MLXSW_REG_MTPTPT_TRAP_ID_PTP0, 0);
-       rhashtable_free_and_destroy(&ptp_state->unmatched_ht,
-                                   &mlxsw_sp1_ptp_unmatched_free_fn, NULL);
+       rhltable_free_and_destroy(&ptp_state->unmatched_ht,
+                                 &mlxsw_sp1_ptp_unmatched_free_fn, NULL);
        kfree(ptp_state);
 }
 
index 59487d446a098d6e620f09b6582c15f11c524162..b894bc0c9c1685c31d449fd61ab6466db5258c17 100644 (file)
@@ -13,12 +13,6 @@ struct ocelot_port_block {
        struct ocelot_port *port;
 };
 
-static u16 get_prio(u32 prio)
-{
-       /* prio starts from 0x1000 while the ids starts from 0 */
-       return prio >> 16;
-}
-
 static int ocelot_flower_parse_action(struct flow_cls_offload *f,
                                      struct ocelot_ace_rule *rule)
 {
@@ -168,7 +162,7 @@ static int ocelot_flower_parse(struct flow_cls_offload *f,
        }
 
 finished_key_parsing:
-       ocelot_rule->prio = get_prio(f->common.prio);
+       ocelot_rule->prio = f->common.prio;
        ocelot_rule->id = f->cookie;
        return ocelot_flower_parse_action(f, ocelot_rule);
 }
@@ -218,7 +212,7 @@ static int ocelot_flower_destroy(struct flow_cls_offload *f,
        struct ocelot_ace_rule rule;
        int ret;
 
-       rule.prio = get_prio(f->common.prio);
+       rule.prio = f->common.prio;
        rule.port = port_block->port;
        rule.id = f->cookie;
 
@@ -236,7 +230,7 @@ static int ocelot_flower_stats_update(struct flow_cls_offload *f,
        struct ocelot_ace_rule rule;
        int ret;
 
-       rule.prio = get_prio(f->common.prio);
+       rule.prio = f->common.prio;
        rule.port = port_block->port;
        rule.id = f->cookie;
        ret = ocelot_ace_rule_stats_update(&rule);
index d8b7fba96d58ed109a4962e0128909f9ea283e50..337b0cbfd153ef6bdabcbd8f4e26a1b21bfb2b00 100644 (file)
@@ -3919,7 +3919,7 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
         * setup (if available). */
        status = myri10ge_request_irq(mgp);
        if (status != 0)
-               goto abort_with_firmware;
+               goto abort_with_slices;
        myri10ge_free_irq(mgp);
 
        /* Save configuration space to be restored if the
index 86e968cd5ffd3dc6ce9cc17ef29bffeb59ec5caa..124a43dc136a8a28ba1e4a971f6ded621cfaf7e6 100644 (file)
@@ -93,7 +93,7 @@ nfp_flower_install_rate_limiter(struct nfp_app *app, struct net_device *netdev,
                return -EOPNOTSUPP;
        }
 
-       if (flow->common.prio != (1 << 16)) {
+       if (flow->common.prio != 1) {
                NL_SET_ERR_MSG_MOD(extack, "unsupported offload: qos rate limit offload requires highest priority");
                return -EOPNOTSUPP;
        }
index ef8f08931fe8b9d3cb75daee8a09c18aaa858f5f..6cacd5e893acacfd5da3bc16444de50acd89e764 100644 (file)
@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0
 /* Renesas Ethernet AVB device driver
  *
- * Copyright (C) 2014-2015 Renesas Electronics Corporation
+ * Copyright (C) 2014-2019 Renesas Electronics Corporation
  * Copyright (C) 2015 Renesas Solutions Corp.
  * Copyright (C) 2015-2016 Cogent Embedded, Inc. <source@cogentembedded.com>
  *
@@ -513,7 +513,10 @@ static void ravb_get_tx_tstamp(struct net_device *ndev)
                        kfree(ts_skb);
                        if (tag == tfa_tag) {
                                skb_tstamp_tx(skb, &shhwtstamps);
+                               dev_consume_skb_any(skb);
                                break;
+                       } else {
+                               dev_kfree_skb_any(skb);
                        }
                }
                ravb_modify(ndev, TCCR, TCCR_TFR, TCCR_TFR);
@@ -1564,7 +1567,7 @@ static netdev_tx_t ravb_start_xmit(struct sk_buff *skb, struct net_device *ndev)
                        }
                        goto unmap;
                }
-               ts_skb->skb = skb;
+               ts_skb->skb = skb_get(skb);
                ts_skb->tag = priv->ts_skb_tag++;
                priv->ts_skb_tag &= 0x3ff;
                list_add_tail(&ts_skb->list, &priv->ts_skb_list);
@@ -1693,6 +1696,7 @@ static int ravb_close(struct net_device *ndev)
        /* Clear the timestamp list */
        list_for_each_entry_safe(ts_skb, ts_skb2, &priv->ts_skb_list, list) {
                list_del(&ts_skb->list);
+               kfree_skb(ts_skb->skb);
                kfree(ts_skb);
        }
 
index 37c0bc699cd9ca80dbfdb77e7893abaad150fe62..6c305b6ecad04a9077f15e6f063bc5aba6914561 100644 (file)
@@ -94,7 +94,7 @@ static int tc_fill_entry(struct stmmac_priv *priv,
        struct stmmac_tc_entry *entry, *frag = NULL;
        struct tc_u32_sel *sel = cls->knode.sel;
        u32 off, data, mask, real_off, rem;
-       u32 prio = cls->common.prio;
+       u32 prio = cls->common.prio << 16;
        int ret;
 
        /* Only 1 match per entry */
index 8479a440527b8902cfc6b1b5cd25ef34c6171e7b..12466a72cefceafa86830a1f68280f432da3ffb5 100644 (file)
@@ -1504,7 +1504,7 @@ tc35815_rx(struct net_device *dev, int limit)
                        pci_unmap_single(lp->pci_dev,
                                         lp->rx_skbs[cur_bd].skb_dma,
                                         RX_BUF_SIZE, PCI_DMA_FROMDEVICE);
-                       if (!HAVE_DMA_RXALIGN(lp) && NET_IP_ALIGN)
+                       if (!HAVE_DMA_RXALIGN(lp) && NET_IP_ALIGN != 0)
                                memmove(skb->data, skb->data - NET_IP_ALIGN,
                                        pkt_len);
                        data = skb_put(skb, pkt_len);
index 78a7de3fb622f4d98fae24768297caa9bcf1003c..c62f474b6d08eb74c159811c9ea32549845072e9 100644 (file)
@@ -371,9 +371,10 @@ tsi108_stat_carry_one(int carry, int carry_bit, int carry_shift,
 static void tsi108_stat_carry(struct net_device *dev)
 {
        struct tsi108_prv_data *data = netdev_priv(dev);
+       unsigned long flags;
        u32 carry1, carry2;
 
-       spin_lock_irq(&data->misclock);
+       spin_lock_irqsave(&data->misclock, flags);
 
        carry1 = TSI_READ(TSI108_STAT_CARRY1);
        carry2 = TSI_READ(TSI108_STAT_CARRY2);
@@ -441,7 +442,7 @@ static void tsi108_stat_carry(struct net_device *dev)
                              TSI108_STAT_TXPAUSEDROP_CARRY,
                              &data->tx_pause_drop);
 
-       spin_unlock_irq(&data->misclock);
+       spin_unlock_irqrestore(&data->misclock, flags);
 }
 
 /* Read a stat counter atomically with respect to carries.
index 3544e19915792df3e162b83983bdbf4647a42ab7..e8fce6d715ef069fe2e482b014b4d3f6e4f3e088 100644 (file)
@@ -1239,12 +1239,15 @@ static void netvsc_get_stats64(struct net_device *net,
                               struct rtnl_link_stats64 *t)
 {
        struct net_device_context *ndev_ctx = netdev_priv(net);
-       struct netvsc_device *nvdev = rcu_dereference_rtnl(ndev_ctx->nvdev);
+       struct netvsc_device *nvdev;
        struct netvsc_vf_pcpu_stats vf_tot;
        int i;
 
+       rcu_read_lock();
+
+       nvdev = rcu_dereference(ndev_ctx->nvdev);
        if (!nvdev)
-               return;
+               goto out;
 
        netdev_stats_to_stats64(t, &net->stats);
 
@@ -1283,6 +1286,8 @@ static void netvsc_get_stats64(struct net_device *net,
                t->rx_packets   += packets;
                t->multicast    += multicast;
        }
+out:
+       rcu_read_unlock();
 }
 
 static int netvsc_set_mac_addr(struct net_device *ndev, void *p)
index c5c417a3c0ce71d46bf1c5e4dd77dfd261b26407..bcc40a2366248be1954f4ba7d67184009b58e548 100644 (file)
@@ -73,46 +73,47 @@ static void nsim_dev_port_debugfs_exit(struct nsim_dev_port *nsim_dev_port)
        debugfs_remove_recursive(nsim_dev_port->ddir);
 }
 
+static struct net *nsim_devlink_net(struct devlink *devlink)
+{
+       return &init_net;
+}
+
 static u64 nsim_dev_ipv4_fib_resource_occ_get(void *priv)
 {
-       struct nsim_dev *nsim_dev = priv;
+       struct net *net = priv;
 
-       return nsim_fib_get_val(nsim_dev->fib_data,
-                               NSIM_RESOURCE_IPV4_FIB, false);
+       return nsim_fib_get_val(net, NSIM_RESOURCE_IPV4_FIB, false);
 }
 
 static u64 nsim_dev_ipv4_fib_rules_res_occ_get(void *priv)
 {
-       struct nsim_dev *nsim_dev = priv;
+       struct net *net = priv;
 
-       return nsim_fib_get_val(nsim_dev->fib_data,
-                               NSIM_RESOURCE_IPV4_FIB_RULES, false);
+       return nsim_fib_get_val(net, NSIM_RESOURCE_IPV4_FIB_RULES, false);
 }
 
 static u64 nsim_dev_ipv6_fib_resource_occ_get(void *priv)
 {
-       struct nsim_dev *nsim_dev = priv;
+       struct net *net = priv;
 
-       return nsim_fib_get_val(nsim_dev->fib_data,
-                               NSIM_RESOURCE_IPV6_FIB, false);
+       return nsim_fib_get_val(net, NSIM_RESOURCE_IPV6_FIB, false);
 }
 
 static u64 nsim_dev_ipv6_fib_rules_res_occ_get(void *priv)
 {
-       struct nsim_dev *nsim_dev = priv;
+       struct net *net = priv;
 
-       return nsim_fib_get_val(nsim_dev->fib_data,
-                               NSIM_RESOURCE_IPV6_FIB_RULES, false);
+       return nsim_fib_get_val(net, NSIM_RESOURCE_IPV6_FIB_RULES, false);
 }
 
 static int nsim_dev_resources_register(struct devlink *devlink)
 {
-       struct nsim_dev *nsim_dev = devlink_priv(devlink);
        struct devlink_resource_size_params params = {
                .size_max = (u64)-1,
                .size_granularity = 1,
                .unit = DEVLINK_RESOURCE_UNIT_ENTRY
        };
+       struct net *net = nsim_devlink_net(devlink);
        int err;
        u64 n;
 
@@ -126,8 +127,7 @@ static int nsim_dev_resources_register(struct devlink *devlink)
                goto out;
        }
 
-       n = nsim_fib_get_val(nsim_dev->fib_data,
-                            NSIM_RESOURCE_IPV4_FIB, true);
+       n = nsim_fib_get_val(net, NSIM_RESOURCE_IPV4_FIB, true);
        err = devlink_resource_register(devlink, "fib", n,
                                        NSIM_RESOURCE_IPV4_FIB,
                                        NSIM_RESOURCE_IPV4, &params);
@@ -136,8 +136,7 @@ static int nsim_dev_resources_register(struct devlink *devlink)
                return err;
        }
 
-       n = nsim_fib_get_val(nsim_dev->fib_data,
-                            NSIM_RESOURCE_IPV4_FIB_RULES, true);
+       n = nsim_fib_get_val(net, NSIM_RESOURCE_IPV4_FIB_RULES, true);
        err = devlink_resource_register(devlink, "fib-rules", n,
                                        NSIM_RESOURCE_IPV4_FIB_RULES,
                                        NSIM_RESOURCE_IPV4, &params);
@@ -156,8 +155,7 @@ static int nsim_dev_resources_register(struct devlink *devlink)
                goto out;
        }
 
-       n = nsim_fib_get_val(nsim_dev->fib_data,
-                            NSIM_RESOURCE_IPV6_FIB, true);
+       n = nsim_fib_get_val(net, NSIM_RESOURCE_IPV6_FIB, true);
        err = devlink_resource_register(devlink, "fib", n,
                                        NSIM_RESOURCE_IPV6_FIB,
                                        NSIM_RESOURCE_IPV6, &params);
@@ -166,8 +164,7 @@ static int nsim_dev_resources_register(struct devlink *devlink)
                return err;
        }
 
-       n = nsim_fib_get_val(nsim_dev->fib_data,
-                            NSIM_RESOURCE_IPV6_FIB_RULES, true);
+       n = nsim_fib_get_val(net, NSIM_RESOURCE_IPV6_FIB_RULES, true);
        err = devlink_resource_register(devlink, "fib-rules", n,
                                        NSIM_RESOURCE_IPV6_FIB_RULES,
                                        NSIM_RESOURCE_IPV6, &params);
@@ -179,19 +176,19 @@ static int nsim_dev_resources_register(struct devlink *devlink)
        devlink_resource_occ_get_register(devlink,
                                          NSIM_RESOURCE_IPV4_FIB,
                                          nsim_dev_ipv4_fib_resource_occ_get,
-                                         nsim_dev);
+                                         net);
        devlink_resource_occ_get_register(devlink,
                                          NSIM_RESOURCE_IPV4_FIB_RULES,
                                          nsim_dev_ipv4_fib_rules_res_occ_get,
-                                         nsim_dev);
+                                         net);
        devlink_resource_occ_get_register(devlink,
                                          NSIM_RESOURCE_IPV6_FIB,
                                          nsim_dev_ipv6_fib_resource_occ_get,
-                                         nsim_dev);
+                                         net);
        devlink_resource_occ_get_register(devlink,
                                          NSIM_RESOURCE_IPV6_FIB_RULES,
                                          nsim_dev_ipv6_fib_rules_res_occ_get,
-                                         nsim_dev);
+                                         net);
 out:
        return err;
 }
@@ -199,11 +196,11 @@ out:
 static int nsim_dev_reload(struct devlink *devlink,
                           struct netlink_ext_ack *extack)
 {
-       struct nsim_dev *nsim_dev = devlink_priv(devlink);
        enum nsim_resource_id res_ids[] = {
                NSIM_RESOURCE_IPV4_FIB, NSIM_RESOURCE_IPV4_FIB_RULES,
                NSIM_RESOURCE_IPV6_FIB, NSIM_RESOURCE_IPV6_FIB_RULES
        };
+       struct net *net = nsim_devlink_net(devlink);
        int i;
 
        for (i = 0; i < ARRAY_SIZE(res_ids); ++i) {
@@ -212,8 +209,7 @@ static int nsim_dev_reload(struct devlink *devlink,
 
                err = devlink_resource_size_get(devlink, res_ids[i], &val);
                if (!err) {
-                       err = nsim_fib_set_max(nsim_dev->fib_data,
-                                              res_ids[i], val, extack);
+                       err = nsim_fib_set_max(net, res_ids[i], val, extack);
                        if (err)
                                return err;
                }
@@ -285,15 +281,9 @@ nsim_dev_create(struct nsim_bus_dev *nsim_bus_dev, unsigned int port_count)
        mutex_init(&nsim_dev->port_list_lock);
        nsim_dev->fw_update_status = true;
 
-       nsim_dev->fib_data = nsim_fib_create();
-       if (IS_ERR(nsim_dev->fib_data)) {
-               err = PTR_ERR(nsim_dev->fib_data);
-               goto err_devlink_free;
-       }
-
        err = nsim_dev_resources_register(devlink);
        if (err)
-               goto err_fib_destroy;
+               goto err_devlink_free;
 
        err = devlink_register(devlink, &nsim_bus_dev->dev);
        if (err)
@@ -315,8 +305,6 @@ err_dl_unregister:
        devlink_unregister(devlink);
 err_resources_unregister:
        devlink_resources_unregister(devlink, NULL);
-err_fib_destroy:
-       nsim_fib_destroy(nsim_dev->fib_data);
 err_devlink_free:
        devlink_free(devlink);
        return ERR_PTR(err);
@@ -330,7 +318,6 @@ static void nsim_dev_destroy(struct nsim_dev *nsim_dev)
        nsim_dev_debugfs_exit(nsim_dev);
        devlink_unregister(devlink);
        devlink_resources_unregister(devlink, NULL);
-       nsim_fib_destroy(nsim_dev->fib_data);
        mutex_destroy(&nsim_dev->port_list_lock);
        devlink_free(devlink);
 }
index 8c57ba7477726650bb6c0b188a2c8ebb989b14d7..f61d094746c069bb7ac1c6db9eb77fe0820d2562 100644 (file)
@@ -18,6 +18,7 @@
 #include <net/ip_fib.h>
 #include <net/ip6_fib.h>
 #include <net/fib_rules.h>
+#include <net/netns/generic.h>
 
 #include "netdevsim.h"
 
@@ -32,14 +33,15 @@ struct nsim_per_fib_data {
 };
 
 struct nsim_fib_data {
-       struct notifier_block fib_nb;
        struct nsim_per_fib_data ipv4;
        struct nsim_per_fib_data ipv6;
 };
 
-u64 nsim_fib_get_val(struct nsim_fib_data *fib_data,
-                    enum nsim_resource_id res_id, bool max)
+static unsigned int nsim_fib_net_id;
+
+u64 nsim_fib_get_val(struct net *net, enum nsim_resource_id res_id, bool max)
 {
+       struct nsim_fib_data *fib_data = net_generic(net, nsim_fib_net_id);
        struct nsim_fib_entry *entry;
 
        switch (res_id) {
@@ -62,10 +64,10 @@ u64 nsim_fib_get_val(struct nsim_fib_data *fib_data,
        return max ? entry->max : entry->num;
 }
 
-int nsim_fib_set_max(struct nsim_fib_data *fib_data,
-                    enum nsim_resource_id res_id, u64 val,
+int nsim_fib_set_max(struct net *net, enum nsim_resource_id res_id, u64 val,
                     struct netlink_ext_ack *extack)
 {
+       struct nsim_fib_data *fib_data = net_generic(net, nsim_fib_net_id);
        struct nsim_fib_entry *entry;
        int err = 0;
 
@@ -118,9 +120,9 @@ static int nsim_fib_rule_account(struct nsim_fib_entry *entry, bool add,
        return err;
 }
 
-static int nsim_fib_rule_event(struct nsim_fib_data *data,
-                              struct fib_notifier_info *info, bool add)
+static int nsim_fib_rule_event(struct fib_notifier_info *info, bool add)
 {
+       struct nsim_fib_data *data = net_generic(info->net, nsim_fib_net_id);
        struct netlink_ext_ack *extack = info->extack;
        int err = 0;
 
@@ -155,9 +157,9 @@ static int nsim_fib_account(struct nsim_fib_entry *entry, bool add,
        return err;
 }
 
-static int nsim_fib_event(struct nsim_fib_data *data,
-                         struct fib_notifier_info *info, bool add)
+static int nsim_fib_event(struct fib_notifier_info *info, bool add)
 {
+       struct nsim_fib_data *data = net_generic(info->net, nsim_fib_net_id);
        struct netlink_ext_ack *extack = info->extack;
        int err = 0;
 
@@ -176,22 +178,18 @@ static int nsim_fib_event(struct nsim_fib_data *data,
 static int nsim_fib_event_nb(struct notifier_block *nb, unsigned long event,
                             void *ptr)
 {
-       struct nsim_fib_data *data = container_of(nb, struct nsim_fib_data,
-                                                 fib_nb);
        struct fib_notifier_info *info = ptr;
        int err = 0;
 
        switch (event) {
        case FIB_EVENT_RULE_ADD: /* fall through */
        case FIB_EVENT_RULE_DEL:
-               err = nsim_fib_rule_event(data, info,
-                                         event == FIB_EVENT_RULE_ADD);
+               err = nsim_fib_rule_event(info, event == FIB_EVENT_RULE_ADD);
                break;
 
        case FIB_EVENT_ENTRY_ADD:  /* fall through */
        case FIB_EVENT_ENTRY_DEL:
-               err = nsim_fib_event(data, info,
-                                    event == FIB_EVENT_ENTRY_ADD);
+               err = nsim_fib_event(info, event == FIB_EVENT_ENTRY_ADD);
                break;
        }
 
@@ -201,23 +199,30 @@ static int nsim_fib_event_nb(struct notifier_block *nb, unsigned long event,
 /* inconsistent dump, trying again */
 static void nsim_fib_dump_inconsistent(struct notifier_block *nb)
 {
-       struct nsim_fib_data *data = container_of(nb, struct nsim_fib_data,
-                                                 fib_nb);
+       struct nsim_fib_data *data;
+       struct net *net;
+
+       rcu_read_lock();
+       for_each_net_rcu(net) {
+               data = net_generic(net, nsim_fib_net_id);
+
+               data->ipv4.fib.num = 0ULL;
+               data->ipv4.rules.num = 0ULL;
 
-       data->ipv4.fib.num = 0ULL;
-       data->ipv4.rules.num = 0ULL;
-       data->ipv6.fib.num = 0ULL;
-       data->ipv6.rules.num = 0ULL;
+               data->ipv6.fib.num = 0ULL;
+               data->ipv6.rules.num = 0ULL;
+       }
+       rcu_read_unlock();
 }
 
-struct nsim_fib_data *nsim_fib_create(void)
-{
-       struct nsim_fib_data *data;
-       int err;
+static struct notifier_block nsim_fib_nb = {
+       .notifier_call = nsim_fib_event_nb,
+};
 
-       data = kzalloc(sizeof(*data), GFP_KERNEL);
-       if (!data)
-               return ERR_PTR(-ENOMEM);
+/* Initialize per network namespace state */
+static int __net_init nsim_fib_netns_init(struct net *net)
+{
+       struct nsim_fib_data *data = net_generic(net, nsim_fib_net_id);
 
        data->ipv4.fib.max = (u64)-1;
        data->ipv4.rules.max = (u64)-1;
@@ -225,22 +230,37 @@ struct nsim_fib_data *nsim_fib_create(void)
        data->ipv6.fib.max = (u64)-1;
        data->ipv6.rules.max = (u64)-1;
 
-       data->fib_nb.notifier_call = nsim_fib_event_nb;
-       err = register_fib_notifier(&data->fib_nb, nsim_fib_dump_inconsistent);
-       if (err) {
-               pr_err("Failed to register fib notifier\n");
-               goto err_out;
-       }
+       return 0;
+}
 
-       return data;
+static struct pernet_operations nsim_fib_net_ops = {
+       .init = nsim_fib_netns_init,
+       .id   = &nsim_fib_net_id,
+       .size = sizeof(struct nsim_fib_data),
+};
 
-err_out:
-       kfree(data);
-       return ERR_PTR(err);
+void nsim_fib_exit(void)
+{
+       unregister_pernet_subsys(&nsim_fib_net_ops);
+       unregister_fib_notifier(&nsim_fib_nb);
 }
 
-void nsim_fib_destroy(struct nsim_fib_data *data)
+int nsim_fib_init(void)
 {
-       unregister_fib_notifier(&data->fib_nb);
-       kfree(data);
+       int err;
+
+       err = register_pernet_subsys(&nsim_fib_net_ops);
+       if (err < 0) {
+               pr_err("Failed to register pernet subsystem\n");
+               goto err_out;
+       }
+
+       err = register_fib_notifier(&nsim_fib_nb, nsim_fib_dump_inconsistent);
+       if (err < 0) {
+               pr_err("Failed to register fib notifier\n");
+               goto err_out;
+       }
+
+err_out:
+       return err;
 }
index 0740940f41b12949558b6150edec27917d3cfe3c..55f57f76d01bb014e8c79b93c739cb1da29460a5 100644 (file)
@@ -357,12 +357,18 @@ static int __init nsim_module_init(void)
        if (err)
                goto err_dev_exit;
 
-       err = rtnl_link_register(&nsim_link_ops);
+       err = nsim_fib_init();
        if (err)
                goto err_bus_exit;
 
+       err = rtnl_link_register(&nsim_link_ops);
+       if (err)
+               goto err_fib_exit;
+
        return 0;
 
+err_fib_exit:
+       nsim_fib_exit();
 err_bus_exit:
        nsim_bus_exit();
 err_dev_exit:
@@ -373,6 +379,7 @@ err_dev_exit:
 static void __exit nsim_module_exit(void)
 {
        rtnl_link_unregister(&nsim_link_ops);
+       nsim_fib_exit();
        nsim_bus_exit();
        nsim_dev_exit();
 }
index 79c05af2a7c0505d6f68eb1345d7629afa61d5b6..9404637d34b7ab30da70c32492abec2b1c07558b 100644 (file)
@@ -169,12 +169,10 @@ int nsim_dev_port_add(struct nsim_bus_dev *nsim_bus_dev,
 int nsim_dev_port_del(struct nsim_bus_dev *nsim_bus_dev,
                      unsigned int port_index);
 
-struct nsim_fib_data *nsim_fib_create(void);
-void nsim_fib_destroy(struct nsim_fib_data *fib_data);
-u64 nsim_fib_get_val(struct nsim_fib_data *fib_data,
-                    enum nsim_resource_id res_id, bool max);
-int nsim_fib_set_max(struct nsim_fib_data *fib_data,
-                    enum nsim_resource_id res_id, u64 val,
+int nsim_fib_init(void);
+void nsim_fib_exit(void);
+u64 nsim_fib_get_val(struct net *net, enum nsim_resource_id res_id, bool max);
+int nsim_fib_set_max(struct net *net, enum nsim_resource_id res_id, u64 val,
                     struct netlink_ext_ack *extack);
 
 #if IS_ENABLED(CONFIG_XFRM_OFFLOAD)
index 222ccd9ecfcebc0bf92beb82e177fba7c3bfaea5..6ad8b1c63c3426c9f7a554eceb6033bab675be62 100644 (file)
@@ -257,36 +257,20 @@ static int at803x_config_init(struct phy_device *phydev)
         *   after HW reset: RX delay enabled and TX delay disabled
         *   after SW reset: RX delay enabled, while TX delay retains the
         *   value before reset.
-        *
-        * So let's first disable the RX and TX delays in PHY and enable
-        * them based on the mode selected (this also takes care of RGMII
-        * mode where we expect delays to be disabled)
         */
-
-       ret = at803x_disable_rx_delay(phydev);
-       if (ret < 0)
-               return ret;
-       ret = at803x_disable_tx_delay(phydev);
-       if (ret < 0)
-               return ret;
-
        if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
-           phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) {
-               /* If RGMII_ID or RGMII_RXID are specified enable RX delay,
-                * otherwise keep it disabled
-                */
+           phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID)
                ret = at803x_enable_rx_delay(phydev);
-               if (ret < 0)
-                       return ret;
-       }
+       else
+               ret = at803x_disable_rx_delay(phydev);
+       if (ret < 0)
+               return ret;
 
        if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
-           phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) {
-               /* If RGMII_ID or RGMII_TXID are specified enable TX delay,
-                * otherwise keep it disabled
-                */
+           phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID)
                ret = at803x_enable_tx_delay(phydev);
-       }
+       else
+               ret = at803x_disable_tx_delay(phydev);
 
        return ret;
 }
index b9d4145781caa092625adb94214549a02b66fd50..58bb25e4af1066ab8d4cc624884e247e37c6c5a7 100644 (file)
@@ -219,6 +219,20 @@ int genphy_c45_read_link(struct phy_device *phydev)
        int val, devad;
        bool link = true;
 
+       if (phydev->c45_ids.devices_in_package & MDIO_DEVS_AN) {
+               val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_CTRL1);
+               if (val < 0)
+                       return val;
+
+               /* Autoneg is being started, therefore disregard current
+                * link status and report link as down.
+                */
+               if (val & MDIO_AN_CTRL1_RESTART) {
+                       phydev->link = 0;
+                       return 0;
+               }
+       }
+
        while (mmd_mask && link) {
                devad = __ffs(mmd_mask);
                mmd_mask &= ~BIT(devad);
index 7ddd91df99e3dc24db6d374ba7b5e911c4716f47..27ebc2c6c2d0c4eb111f39a5596f50d976ca4a1a 100644 (file)
@@ -1752,7 +1752,17 @@ EXPORT_SYMBOL(genphy_aneg_done);
  */
 int genphy_update_link(struct phy_device *phydev)
 {
-       int status;
+       int status = 0, bmcr;
+
+       bmcr = phy_read(phydev, MII_BMCR);
+       if (bmcr < 0)
+               return bmcr;
+
+       /* Autoneg is being started, therefore disregard BMSR value and
+        * report link as down.
+        */
+       if (bmcr & BMCR_ANRESTART)
+               goto done;
 
        /* The link state is latched low so that momentary link
         * drops can be detected. Do not double-read the status
index abfa0da9bbd28d8765867e2e4920cd4bf029a229..e8089def5a4671bad10efbde7b00297e4c37df69 100644 (file)
@@ -1004,6 +1004,8 @@ static void __team_compute_features(struct team *team)
 
        team->dev->vlan_features = vlan_features;
        team->dev->hw_enc_features = enc_features | NETIF_F_GSO_ENCAP_ALL |
+                                    NETIF_F_HW_VLAN_CTAG_TX |
+                                    NETIF_F_HW_VLAN_STAG_TX |
                                     NETIF_F_GSO_UDP_L4;
        team->dev->hard_header_len = max_hard_header_len;
 
index 5519248a791ebefd9003ae6892894f2d95b96a03..32b08b18e12086f9634284b54a2f336994986092 100644 (file)
@@ -163,7 +163,8 @@ static int cx82310_bind(struct usbnet *dev, struct usb_interface *intf)
        }
        if (!timeout) {
                dev_err(&udev->dev, "firmware not ready in time\n");
-               return -ETIMEDOUT;
+               ret = -ETIMEDOUT;
+               goto err;
        }
 
        /* enable ethernet mode (?) */
index d62b6706a5376a6f50834721ec32297ff3481bc7..fc5895f85cee2f8256661f37de0802054826d421 100644 (file)
@@ -113,16 +113,16 @@ kalmia_init_and_get_ethernet_addr(struct usbnet *dev, u8 *ethernet_addr)
        status = kalmia_send_init_packet(dev, usb_buf, ARRAY_SIZE(init_msg_1),
                                         usb_buf, 24);
        if (status != 0)
-               return status;
+               goto out;
 
        memcpy(usb_buf, init_msg_2, 12);
        status = kalmia_send_init_packet(dev, usb_buf, ARRAY_SIZE(init_msg_2),
                                         usb_buf, 28);
        if (status != 0)
-               return status;
+               goto out;
 
        memcpy(ethernet_addr, usb_buf + 10, ETH_ALEN);
-
+out:
        kfree(usb_buf);
        return status;
 }
index 3d92ea6fcc02be12c00083cdc71832745c8a70fb..f033fee225a11cc7c5b977d26f639042f7896524 100644 (file)
@@ -3792,7 +3792,7 @@ static int lan78xx_probe(struct usb_interface *intf,
        ret = register_netdev(netdev);
        if (ret != 0) {
                netif_err(dev, probe, netdev, "couldn't register the device\n");
-               goto out3;
+               goto out4;
        }
 
        usb_set_intfdata(intf, dev);
@@ -3807,12 +3807,14 @@ static int lan78xx_probe(struct usb_interface *intf,
 
        ret = lan78xx_phy_init(dev);
        if (ret < 0)
-               goto out4;
+               goto out5;
 
        return 0;
 
-out4:
+out5:
        unregister_netdev(netdev);
+out4:
+       usb_free_urb(dev->urb_intr);
 out3:
        lan78xx_unbind(dev, intf);
 out2:
index e9fc168bb734504e535be77067dd250a8197bffe..489cba9b284d1b3bf633853c2f1f5de57e1533c2 100644 (file)
@@ -351,13 +351,15 @@ int i2400m_barker_db_init(const char *_options)
                        }
                        result = i2400m_barker_db_add(barker);
                        if (result < 0)
-                               goto error_add;
+                               goto error_parse_add;
                }
                kfree(options_orig);
        }
        return 0;
 
+error_parse_add:
 error_parse:
+       kfree(options_orig);
 error_add:
        kfree(i2400m_barker_db);
        return result;
index 1d9940d4e8c7d0b627d428589325c10012971af2..c9262ffeefe4cb3eb8a13dfdcc0b77801adc5876 100644 (file)
@@ -925,6 +925,7 @@ static void xenvif_tx_build_gops(struct xenvif_queue *queue,
                        skb_shinfo(skb)->nr_frags = MAX_SKB_FRAGS;
                        nskb = xenvif_alloc_skb(0);
                        if (unlikely(nskb == NULL)) {
+                               skb_shinfo(skb)->nr_frags = 0;
                                kfree_skb(skb);
                                xenvif_tx_err(queue, &txreq, extra_count, idx);
                                if (net_ratelimit())
@@ -940,6 +941,7 @@ static void xenvif_tx_build_gops(struct xenvif_queue *queue,
 
                        if (xenvif_set_skb_gso(queue->vif, skb, gso)) {
                                /* Failure in xenvif_set_skb_gso is fatal. */
+                               skb_shinfo(skb)->nr_frags = 0;
                                kfree_skb(skb);
                                kfree_skb(nskb);
                                break;
index c258a1ce4b28aaa3d4f021f30213e80132d2a076..d3d6b7bd690335d072d265e8646d090bdc2ab2e4 100644 (file)
@@ -2257,6 +2257,16 @@ static const struct nvme_core_quirk_entry core_quirks[] = {
                .vid = 0x1179,
                .mn = "THNSF5256GPUK TOSHIBA",
                .quirks = NVME_QUIRK_NO_APST,
+       },
+       {
+               /*
+                * This LiteON CL1-3D*-Q11 firmware version has a race
+                * condition associated with actions related to suspend to idle
+                * LiteON has resolved the problem in future firmware
+                */
+               .vid = 0x14a4,
+               .fr = "22301111",
+               .quirks = NVME_QUIRK_SIMPLE_SUSPEND,
        }
 };
 
@@ -2597,6 +2607,9 @@ int nvme_init_identify(struct nvme_ctrl *ctrl)
                        goto out_free;
        }
 
+       if (!(ctrl->ops->flags & NVME_F_FABRICS))
+               ctrl->cntlid = le16_to_cpu(id->cntlid);
+
        if (!ctrl->identified) {
                int i;
 
@@ -2697,7 +2710,6 @@ int nvme_init_identify(struct nvme_ctrl *ctrl)
                        goto out_free;
                }
        } else {
-               ctrl->cntlid = le16_to_cpu(id->cntlid);
                ctrl->hmpre = le32_to_cpu(id->hmpre);
                ctrl->hmmin = le32_to_cpu(id->hmmin);
                ctrl->hmminds = le32_to_cpu(id->hmminds);
index 888d4543894e7d74ea9f75a462df1ace4e3b0cec..af831d3d15d072339b20ef297b197bae939b4d55 100644 (file)
@@ -428,6 +428,7 @@ static void nvme_mpath_set_live(struct nvme_ns *ns)
                srcu_read_unlock(&head->srcu, srcu_idx);
        }
 
+       synchronize_srcu(&ns->head->srcu);
        kblockd_schedule_work(&ns->head->requeue_work);
 }
 
index 778b3a0b6adb1f9866c4d7d1b0e2b5c08e277ea9..2d678fb968c745598e20a6b4ca3a839ae425dd5c 100644 (file)
@@ -92,6 +92,11 @@ enum nvme_quirks {
         * Broken Write Zeroes.
         */
        NVME_QUIRK_DISABLE_WRITE_ZEROES         = (1 << 9),
+
+       /*
+        * Force simple suspend/resume path.
+        */
+       NVME_QUIRK_SIMPLE_SUSPEND               = (1 << 10),
 };
 
 /*
index 6bd9b10339654b3d11aa3944f7a51ee264ffb8a2..732d5b63ec0540b1a40566136c4118f34482f5aa 100644 (file)
@@ -2876,7 +2876,8 @@ static int nvme_suspend(struct device *dev)
         * state (which may not be possible if the link is up).
         */
        if (pm_suspend_via_firmware() || !ctrl->npss ||
-           !pcie_aspm_enabled(pdev)) {
+           !pcie_aspm_enabled(pdev) ||
+           (ndev->ctrl.quirks & NVME_QUIRK_SIMPLE_SUSPEND)) {
                nvme_dev_disable(ndev, true);
                return 0;
        }
index 208aacf393297835f89101585b48ae5074a9f290..44c4ae1abd00557e080bf9ca37458c31a7ba7504 100644 (file)
@@ -5256,7 +5256,7 @@ static void quirk_reset_lenovo_thinkpad_p50_nvgpu(struct pci_dev *pdev)
         */
        if (ioread32(map + 0x2240c) & 0x2) {
                pci_info(pdev, FW_BUG "GPU left initialized by EFI, resetting\n");
-               ret = pci_reset_function(pdev);
+               ret = pci_reset_bus(pdev);
                if (ret < 0)
                        pci_err(pdev, "Failed to reset GPU: %d\n", ret);
        }
index e504d255d5ce270967f0a082537f16bf2923aeff..430731cdf8277ba247656ecdb90ce187efe2ddf8 100644 (file)
@@ -707,7 +707,7 @@ static int cros_ec_ishtp_reset(struct ishtp_cl_device *cl_device)
  */
 static int __maybe_unused cros_ec_ishtp_suspend(struct device *device)
 {
-       struct ishtp_cl_device *cl_device = dev_get_drvdata(device);
+       struct ishtp_cl_device *cl_device = ishtp_dev_to_cl_device(device);
        struct ishtp_cl *cros_ish_cl = ishtp_get_drvdata(cl_device);
        struct ishtp_cl_data *client_data = ishtp_get_client_data(cros_ish_cl);
 
@@ -722,7 +722,7 @@ static int __maybe_unused cros_ec_ishtp_suspend(struct device *device)
  */
 static int __maybe_unused cros_ec_ishtp_resume(struct device *device)
 {
-       struct ishtp_cl_device *cl_device = dev_get_drvdata(device);
+       struct ishtp_cl_device *cl_device = ishtp_dev_to_cl_device(device);
        struct ishtp_cl *cros_ish_cl = ishtp_get_drvdata(cl_device);
        struct ishtp_cl_data *client_data = ishtp_get_client_data(cros_ish_cl);
 
index 30de448de802232485703e4b9dfbdb94f831385d..86d88aec94a11a02017afd0f4a396d3b2bffa7dd 100644 (file)
@@ -742,6 +742,7 @@ static int ab8500_charger_max_usb_curr(struct ab8500_charger *di,
                                                USB_CH_IP_CUR_LVL_1P5;
                        break;
                }
+               /* Else, fall through */
        case USB_STAT_HM_IDGND:
                dev_err(di->dev, "USB Type - Charging not allowed\n");
                di->max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_0P05;
index c7ee07ce3615d93a9d02b5a507ca0ef008a9698f..28db887d38edc809669b32fb146fcd8d64185f92 100644 (file)
@@ -629,6 +629,7 @@ struct qeth_seqno {
 struct qeth_reply {
        struct list_head list;
        struct completion received;
+       spinlock_t lock;
        int (*callback)(struct qeth_card *, struct qeth_reply *,
                unsigned long);
        u32 seqno;
index 4d0caeebc80210d3a130a2ec19574e0e1824b1bb..9c3310c4d61d670426bfa5a842b5f2c750119f04 100644 (file)
@@ -544,6 +544,7 @@ static struct qeth_reply *qeth_alloc_reply(struct qeth_card *card)
        if (reply) {
                refcount_set(&reply->refcnt, 1);
                init_completion(&reply->received);
+               spin_lock_init(&reply->lock);
        }
        return reply;
 }
@@ -799,6 +800,13 @@ static void qeth_issue_next_read_cb(struct qeth_card *card,
 
        if (!reply->callback) {
                rc = 0;
+               goto no_callback;
+       }
+
+       spin_lock_irqsave(&reply->lock, flags);
+       if (reply->rc) {
+               /* Bail out when the requestor has already left: */
+               rc = reply->rc;
        } else {
                if (cmd) {
                        reply->offset = (u16)((char *)cmd - (char *)iob->data);
@@ -807,7 +815,9 @@ static void qeth_issue_next_read_cb(struct qeth_card *card,
                        rc = reply->callback(card, reply, (unsigned long)iob);
                }
        }
+       spin_unlock_irqrestore(&reply->lock, flags);
 
+no_callback:
        if (rc <= 0)
                qeth_notify_reply(reply, rc);
        qeth_put_reply(reply);
@@ -1749,6 +1759,16 @@ static int qeth_send_control_data(struct qeth_card *card,
                rc = (timeout == -ERESTARTSYS) ? -EINTR : -ETIME;
 
        qeth_dequeue_reply(card, reply);
+
+       if (reply_cb) {
+               /* Wait until the callback for a late reply has completed: */
+               spin_lock_irq(&reply->lock);
+               if (rc)
+                       /* Zap any callback that's still pending: */
+                       reply->rc = rc;
+               spin_unlock_irq(&reply->lock);
+       }
+
        if (!rc)
                rc = reply->rc;
        qeth_put_reply(reply);
index abcad097ff2f4985413eac39209183751b1e8b14..f47b4b281b14ab5ed05973faf00c2aa09ec5b7c0 100644 (file)
@@ -459,6 +459,7 @@ static void sas_discover_domain(struct work_struct *work)
                pr_notice("ATA device seen but CONFIG_SCSI_SAS_ATA=N so cannot attach\n");
                /* Fall through */
 #endif
+               /* Fall through - only for the #else condition above. */
        default:
                error = -ENXIO;
                pr_err("unhandled device %d\n", dev->dev_type);
index 2c3bb8a966e5af1cc88412c2eb74a3e527d7a03f..bade2e025ecf2c73b2fdf0869d2e0f8652877c0e 100644 (file)
@@ -824,6 +824,7 @@ struct lpfc_hba {
        uint32_t cfg_cq_poll_threshold;
        uint32_t cfg_cq_max_proc_limit;
        uint32_t cfg_fcp_cpu_map;
+       uint32_t cfg_fcp_mq_threshold;
        uint32_t cfg_hdw_queue;
        uint32_t cfg_irq_chann;
        uint32_t cfg_suppress_rsp;
index ea62322ffe2bb7e711bc87d521903573550be282..8d8c495b5b60c87506526aeee498435b9950273b 100644 (file)
@@ -5708,6 +5708,19 @@ LPFC_ATTR_RW(nvme_oas, 0, 0, 1,
 LPFC_ATTR_RW(nvme_embed_cmd, 1, 0, 2,
             "Embed NVME Command in WQE");
 
+/*
+ * lpfc_fcp_mq_threshold: Set the maximum number of Hardware Queues
+ * the driver will advertise it supports to the SCSI layer.
+ *
+ *      0    = Set nr_hw_queues by the number of CPUs or HW queues.
+ *      1,128 = Manually specify the maximum nr_hw_queue value to be set,
+ *
+ * Value range is [0,128]. Default value is 8.
+ */
+LPFC_ATTR_R(fcp_mq_threshold, LPFC_FCP_MQ_THRESHOLD_DEF,
+           LPFC_FCP_MQ_THRESHOLD_MIN, LPFC_FCP_MQ_THRESHOLD_MAX,
+           "Set the number of SCSI Queues advertised");
+
 /*
  * lpfc_hdw_queue: Set the number of Hardware Queues the driver
  * will advertise it supports to the NVME and  SCSI layers. This also
@@ -6030,6 +6043,7 @@ struct device_attribute *lpfc_hba_attrs[] = {
        &dev_attr_lpfc_cq_poll_threshold,
        &dev_attr_lpfc_cq_max_proc_limit,
        &dev_attr_lpfc_fcp_cpu_map,
+       &dev_attr_lpfc_fcp_mq_threshold,
        &dev_attr_lpfc_hdw_queue,
        &dev_attr_lpfc_irq_chann,
        &dev_attr_lpfc_suppress_rsp,
@@ -7112,6 +7126,7 @@ lpfc_get_cfgparam(struct lpfc_hba *phba)
        /* Initialize first burst. Target vs Initiator are different. */
        lpfc_nvme_enable_fb_init(phba, lpfc_nvme_enable_fb);
        lpfc_nvmet_fb_size_init(phba, lpfc_nvmet_fb_size);
+       lpfc_fcp_mq_threshold_init(phba, lpfc_fcp_mq_threshold);
        lpfc_hdw_queue_init(phba, lpfc_hdw_queue);
        lpfc_irq_chann_init(phba, lpfc_irq_chann);
        lpfc_enable_bbcr_init(phba, lpfc_enable_bbcr);
index a7549ae32542738cce6a8c4011911f1462ff09d1..1ac98becb5baf6b64516c47c267a958bee462e77 100644 (file)
@@ -4309,10 +4309,12 @@ lpfc_create_port(struct lpfc_hba *phba, int instance, struct device *dev)
        shost->max_cmd_len = 16;
 
        if (phba->sli_rev == LPFC_SLI_REV4) {
-               if (phba->cfg_fcp_io_sched == LPFC_FCP_SCHED_BY_HDWQ)
-                       shost->nr_hw_queues = phba->cfg_hdw_queue;
-               else
-                       shost->nr_hw_queues = phba->sli4_hba.num_present_cpu;
+               if (!phba->cfg_fcp_mq_threshold ||
+                   phba->cfg_fcp_mq_threshold > phba->cfg_hdw_queue)
+                       phba->cfg_fcp_mq_threshold = phba->cfg_hdw_queue;
+
+               shost->nr_hw_queues = min_t(int, 2 * num_possible_nodes(),
+                                           phba->cfg_fcp_mq_threshold);
 
                shost->dma_boundary =
                        phba->sli4_hba.pc_sli4_params.sge_supp_len-1;
index 3aeca387b22a4d3a253403e269652bb3bf108c94..329f7aa7e169bb2e62d431360f799bab7f0d0b7f 100644 (file)
 #define LPFC_HBA_HDWQ_MAX      128
 #define LPFC_HBA_HDWQ_DEF      0
 
+/* FCP MQ queue count limiting */
+#define LPFC_FCP_MQ_THRESHOLD_MIN      0
+#define LPFC_FCP_MQ_THRESHOLD_MAX      128
+#define LPFC_FCP_MQ_THRESHOLD_DEF      8
+
 /* Common buffer size to accomidate SCSI and NVME IO buffers */
 #define LPFC_COMMON_IO_BUF_SZ  768
 
index 8d560c562e9c06b5828b62d0c576f67ec978b20e..6b7b390b2e5228c238b4415282331fd19eff32d6 100644 (file)
@@ -2956,6 +2956,8 @@ qla24xx_vport_delete(struct fc_vport *fc_vport)
        dma_free_coherent(&ha->pdev->dev, vha->gnl.size, vha->gnl.l,
            vha->gnl.ldma);
 
+       vha->gnl.l = NULL;
+
        vfree(vha->scan.l);
 
        if (vha->qpair && vha->qpair->vp_idx == vha->vp_idx) {
index 2e58cff9d2005b0cab783ab22653cb27e8333ecd..98e60a34afd9c083fa0ed6377c8ef32d4f3fd3c3 100644 (file)
@@ -3440,6 +3440,12 @@ skip_dpc:
        return 0;
 
 probe_failed:
+       if (base_vha->gnl.l) {
+               dma_free_coherent(&ha->pdev->dev, base_vha->gnl.size,
+                               base_vha->gnl.l, base_vha->gnl.ldma);
+               base_vha->gnl.l = NULL;
+       }
+
        if (base_vha->timer_active)
                qla2x00_stop_timer(base_vha);
        base_vha->flags.online = 0;
@@ -3673,7 +3679,7 @@ qla2x00_remove_one(struct pci_dev *pdev)
        if (!atomic_read(&pdev->enable_cnt)) {
                dma_free_coherent(&ha->pdev->dev, base_vha->gnl.size,
                    base_vha->gnl.l, base_vha->gnl.ldma);
-
+               base_vha->gnl.l = NULL;
                scsi_host_put(base_vha->host);
                kfree(ha);
                pci_set_drvdata(pdev, NULL);
@@ -3713,6 +3719,8 @@ qla2x00_remove_one(struct pci_dev *pdev)
        dma_free_coherent(&ha->pdev->dev,
                base_vha->gnl.size, base_vha->gnl.l, base_vha->gnl.ldma);
 
+       base_vha->gnl.l = NULL;
+
        vfree(base_vha->scan.l);
 
        if (IS_QLAFX00(ha))
@@ -4816,6 +4824,7 @@ struct scsi_qla_host *qla2x00_create_host(struct scsi_host_template *sht,
                    "Alloc failed for scan database.\n");
                dma_free_coherent(&ha->pdev->dev, vha->gnl.size,
                    vha->gnl.l, vha->gnl.ldma);
+               vha->gnl.l = NULL;
                scsi_remove_host(vha->host);
                return NULL;
        }
index e274053109d073ae636b43834cbeb7371fb39256..029da74bb2f5c1a0e43efd5ad7bd7d1dc521ec24 100644 (file)
@@ -7062,6 +7062,9 @@ static inline int ufshcd_config_vreg_lpm(struct ufs_hba *hba,
 static inline int ufshcd_config_vreg_hpm(struct ufs_hba *hba,
                                         struct ufs_vreg *vreg)
 {
+       if (!vreg)
+               return 0;
+
        return ufshcd_config_vreg_load(hba->dev, vreg, vreg->max_uA);
 }
 
index 04eda111920ec4cae3d41184cdfac9afde63922c..661bb9358364df814c16fa60614265bce2c8117a 100644 (file)
@@ -1132,14 +1132,16 @@ static void tcmu_handle_completion(struct tcmu_cmd *cmd, struct tcmu_cmd_entry *
        struct se_cmd *se_cmd = cmd->se_cmd;
        struct tcmu_dev *udev = cmd->tcmu_dev;
        bool read_len_valid = false;
-       uint32_t read_len = se_cmd->data_length;
+       uint32_t read_len;
 
        /*
         * cmd has been completed already from timeout, just reclaim
         * data area space and free cmd
         */
-       if (test_bit(TCMU_CMD_BIT_EXPIRED, &cmd->flags))
+       if (test_bit(TCMU_CMD_BIT_EXPIRED, &cmd->flags)) {
+               WARN_ON_ONCE(se_cmd);
                goto out;
+       }
 
        list_del_init(&cmd->queue_entry);
 
@@ -1152,6 +1154,7 @@ static void tcmu_handle_completion(struct tcmu_cmd *cmd, struct tcmu_cmd_entry *
                goto done;
        }
 
+       read_len = se_cmd->data_length;
        if (se_cmd->data_direction == DMA_FROM_DEVICE &&
            (entry->hdr.uflags & TCMU_UFLAG_READ_LEN) && entry->rsp.read_len) {
                read_len_valid = true;
@@ -1307,6 +1310,7 @@ static int tcmu_check_expired_cmd(int id, void *p, void *data)
                 */
                scsi_status = SAM_STAT_CHECK_CONDITION;
                list_del_init(&cmd->queue_entry);
+               cmd->se_cmd = NULL;
        } else {
                list_del_init(&cmd->queue_entry);
                idr_remove(&udev->commands, id);
@@ -2022,6 +2026,7 @@ static void tcmu_reset_ring(struct tcmu_dev *udev, u8 err_level)
 
                idr_remove(&udev->commands, i);
                if (!test_bit(TCMU_CMD_BIT_EXPIRED, &cmd->flags)) {
+                       WARN_ON(!cmd->se_cmd);
                        list_del_init(&cmd->queue_entry);
                        if (err_level == 1) {
                                /*
index 92f23e3bc27a2400cfd14ed9b19017bc648457cf..7cacae5a8797d9faeaa1e8fa572af53ae2dd5f62 100644 (file)
@@ -858,6 +858,7 @@ static void acornfb_parse_dram(char *opt)
                case 'M':
                case 'm':
                        size *= 1024;
+                       /* Fall through */
                case 'K':
                case 'k':
                        size *= 1024;
index 4eacfb1ce1ac61b109292971194e57b7429bb644..eb729d704836b656ccb00972c878cd036f68b8d6 100644 (file)
@@ -168,7 +168,7 @@ static long watchdog_ioctl(struct file *file, unsigned int cmd,
                soft_margin = new_margin;
                reload = soft_margin * (mem_fclk_21285 / 256);
                watchdog_ping();
-               /* Fall */
+               /* Fall through */
        case WDIOC_GETTIMEOUT:
                ret = put_user(soft_margin, int_arg);
                break;
index a2a87117d2626220719cd10e71572c0e5f1b385d..fd5133e26a38b01af89ef488be709eed7987a7c5 100644 (file)
@@ -74,6 +74,7 @@ struct afs_cell *afs_lookup_cell_rcu(struct afs_net *net,
                        cell = rcu_dereference_raw(net->ws_cell);
                        if (cell) {
                                afs_get_cell(cell);
+                               ret = 0;
                                break;
                        }
                        ret = -EDESTADDRREQ;
@@ -108,6 +109,9 @@ struct afs_cell *afs_lookup_cell_rcu(struct afs_net *net,
 
        done_seqretry(&net->cells_lock, seq);
 
+       if (ret != 0 && cell)
+               afs_put_cell(net, cell);
+
        return ret == 0 ? cell : ERR_PTR(ret);
 }
 
index 81207dc3c9977892ece421851666eadf8e818321..139b4e3cc9464d81a72e980d5fc0077a5c8425c4 100644 (file)
@@ -959,7 +959,8 @@ static struct dentry *afs_lookup(struct inode *dir, struct dentry *dentry,
                                 inode ? AFS_FS_I(inode) : NULL);
        } else {
                trace_afs_lookup(dvnode, &dentry->d_name,
-                                inode ? AFS_FS_I(inode) : NULL);
+                                IS_ERR_OR_NULL(inode) ? NULL
+                                : AFS_FS_I(inode));
        }
        return d;
 }
index 2575503170fc126ec6ac0b4be34b83e49fd86a19..ca2452806ebf12ad0081c31ad0bd815cb9c01343 100644 (file)
@@ -2171,7 +2171,7 @@ int yfs_fs_store_opaque_acl2(struct afs_fs_cursor *fc, const struct afs_acl *acl
               key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode);
 
        size = round_up(acl->size, 4);
-       call = afs_alloc_flat_call(net, &yfs_RXYFSStoreStatus,
+       call = afs_alloc_flat_call(net, &yfs_RXYFSStoreOpaqueACL2,
                                   sizeof(__be32) * 2 +
                                   sizeof(struct yfs_xdr_YFSFid) +
                                   sizeof(__be32) + size,
index e078cc55b989e287e8d3891f8294778b995598f5..b3c8b886bf647d71c7d93af58f89d619aa81cd35 100644 (file)
@@ -913,8 +913,9 @@ get_more_pages:
                        if (page_offset(page) >= ceph_wbc.i_size) {
                                dout("%p page eof %llu\n",
                                     page, ceph_wbc.i_size);
-                               if (ceph_wbc.size_stable ||
-                                   page_offset(page) >= i_size_read(inode))
+                               if ((ceph_wbc.size_stable ||
+                                   page_offset(page) >= i_size_read(inode)) &&
+                                   clear_page_dirty_for_io(page))
                                        mapping->a_ops->invalidatepage(page,
                                                                0, PAGE_SIZE);
                                unlock_page(page);
index d98dcd976c8004249c72419b671a6089b350f5f2..ce0f5658720ab9d06764c1f63dbe3d267ffb336f 100644 (file)
@@ -1301,6 +1301,7 @@ static int __send_cap(struct ceph_mds_client *mdsc, struct ceph_cap *cap,
 {
        struct ceph_inode_info *ci = cap->ci;
        struct inode *inode = &ci->vfs_inode;
+       struct ceph_buffer *old_blob = NULL;
        struct cap_msg_args arg;
        int held, revoking;
        int wake = 0;
@@ -1365,7 +1366,7 @@ static int __send_cap(struct ceph_mds_client *mdsc, struct ceph_cap *cap,
        ci->i_requested_max_size = arg.max_size;
 
        if (flushing & CEPH_CAP_XATTR_EXCL) {
-               __ceph_build_xattrs_blob(ci);
+               old_blob = __ceph_build_xattrs_blob(ci);
                arg.xattr_version = ci->i_xattrs.version;
                arg.xattr_buf = ci->i_xattrs.blob;
        } else {
@@ -1409,6 +1410,8 @@ static int __send_cap(struct ceph_mds_client *mdsc, struct ceph_cap *cap,
 
        spin_unlock(&ci->i_ceph_lock);
 
+       ceph_buffer_put(old_blob);
+
        ret = send_cap_msg(&arg);
        if (ret < 0) {
                dout("error sending cap msg, must requeue %p\n", inode);
index 791f84a13bb8e16daad628d07e0e8573024c4a3f..18500edefc56f8f53fd70984116e477cd437b77f 100644 (file)
@@ -736,6 +736,7 @@ static int fill_inode(struct inode *inode, struct page *locked_page,
        int issued, new_issued, info_caps;
        struct timespec64 mtime, atime, ctime;
        struct ceph_buffer *xattr_blob = NULL;
+       struct ceph_buffer *old_blob = NULL;
        struct ceph_string *pool_ns = NULL;
        struct ceph_cap *new_cap = NULL;
        int err = 0;
@@ -881,7 +882,7 @@ static int fill_inode(struct inode *inode, struct page *locked_page,
        if ((ci->i_xattrs.version == 0 || !(issued & CEPH_CAP_XATTR_EXCL))  &&
            le64_to_cpu(info->xattr_version) > ci->i_xattrs.version) {
                if (ci->i_xattrs.blob)
-                       ceph_buffer_put(ci->i_xattrs.blob);
+                       old_blob = ci->i_xattrs.blob;
                ci->i_xattrs.blob = xattr_blob;
                if (xattr_blob)
                        memcpy(ci->i_xattrs.blob->vec.iov_base,
@@ -1022,8 +1023,8 @@ static int fill_inode(struct inode *inode, struct page *locked_page,
 out:
        if (new_cap)
                ceph_put_cap(mdsc, new_cap);
-       if (xattr_blob)
-               ceph_buffer_put(xattr_blob);
+       ceph_buffer_put(old_blob);
+       ceph_buffer_put(xattr_blob);
        ceph_put_string(pool_ns);
        return err;
 }
index ac9b53b893650270b80ccf5a69a954e55346922f..5083e238ad15fdd62ee7c92e5228f67ea69eb493 100644 (file)
@@ -111,8 +111,7 @@ static int ceph_lock_message(u8 lock_type, u16 operation, struct inode *inode,
                req->r_wait_for_completion = ceph_lock_wait_for_completion;
 
        err = ceph_mdsc_do_request(mdsc, inode, req);
-
-       if (operation == CEPH_MDS_OP_GETFILELOCK) {
+       if (!err && operation == CEPH_MDS_OP_GETFILELOCK) {
                fl->fl_pid = -le64_to_cpu(req->r_reply_info.filelock_reply->pid);
                if (CEPH_LOCK_SHARED == req->r_reply_info.filelock_reply->type)
                        fl->fl_type = F_RDLCK;
index 4c6494eb02b535df4c8f0f46d88ea1a8696304a5..ccfcc66aaf442030bd552dfbf8bb4e052fc3c9ee 100644 (file)
@@ -465,6 +465,7 @@ void ceph_queue_cap_snap(struct ceph_inode_info *ci)
        struct inode *inode = &ci->vfs_inode;
        struct ceph_cap_snap *capsnap;
        struct ceph_snap_context *old_snapc, *new_snapc;
+       struct ceph_buffer *old_blob = NULL;
        int used, dirty;
 
        capsnap = kzalloc(sizeof(*capsnap), GFP_NOFS);
@@ -541,7 +542,7 @@ void ceph_queue_cap_snap(struct ceph_inode_info *ci)
        capsnap->gid = inode->i_gid;
 
        if (dirty & CEPH_CAP_XATTR_EXCL) {
-               __ceph_build_xattrs_blob(ci);
+               old_blob = __ceph_build_xattrs_blob(ci);
                capsnap->xattr_blob =
                        ceph_buffer_get(ci->i_xattrs.blob);
                capsnap->xattr_version = ci->i_xattrs.version;
@@ -584,6 +585,7 @@ update_snapc:
        }
        spin_unlock(&ci->i_ceph_lock);
 
+       ceph_buffer_put(old_blob);
        kfree(capsnap);
        ceph_put_snap_context(old_snapc);
 }
index d2352fd95dbc73c4b8ce4f03e586f8a6ba8abda3..6b9f1ee7de8575a7db70fcf49fc16769df01fa3e 100644 (file)
@@ -926,7 +926,7 @@ extern int ceph_getattr(const struct path *path, struct kstat *stat,
 int __ceph_setxattr(struct inode *, const char *, const void *, size_t, int);
 ssize_t __ceph_getxattr(struct inode *, const char *, void *, size_t);
 extern ssize_t ceph_listxattr(struct dentry *, char *, size_t);
-extern void __ceph_build_xattrs_blob(struct ceph_inode_info *ci);
+extern struct ceph_buffer *__ceph_build_xattrs_blob(struct ceph_inode_info *ci);
 extern void __ceph_destroy_xattrs(struct ceph_inode_info *ci);
 extern const struct xattr_handler *ceph_xattr_handlers[];
 
index 37b458a9af3adafafa1b9fc310762762b3ff0841..939eab7aa219d74c652263d4c85c249b7b94898f 100644 (file)
@@ -754,12 +754,15 @@ static int __get_required_blob_size(struct ceph_inode_info *ci, int name_size,
 
 /*
  * If there are dirty xattrs, reencode xattrs into the prealloc_blob
- * and swap into place.
+ * and swap into place.  It returns the old i_xattrs.blob (or NULL) so
+ * that it can be freed by the caller as the i_ceph_lock is likely to be
+ * held.
  */
-void __ceph_build_xattrs_blob(struct ceph_inode_info *ci)
+struct ceph_buffer *__ceph_build_xattrs_blob(struct ceph_inode_info *ci)
 {
        struct rb_node *p;
        struct ceph_inode_xattr *xattr = NULL;
+       struct ceph_buffer *old_blob = NULL;
        void *dest;
 
        dout("__build_xattrs_blob %p\n", &ci->vfs_inode);
@@ -790,12 +793,14 @@ void __ceph_build_xattrs_blob(struct ceph_inode_info *ci)
                        dest - ci->i_xattrs.prealloc_blob->vec.iov_base;
 
                if (ci->i_xattrs.blob)
-                       ceph_buffer_put(ci->i_xattrs.blob);
+                       old_blob = ci->i_xattrs.blob;
                ci->i_xattrs.blob = ci->i_xattrs.prealloc_blob;
                ci->i_xattrs.prealloc_blob = NULL;
                ci->i_xattrs.dirty = false;
                ci->i_xattrs.version++;
        }
+
+       return old_blob;
 }
 
 static inline int __get_request_mask(struct inode *in) {
@@ -1036,6 +1041,7 @@ int __ceph_setxattr(struct inode *inode, const char *name,
        struct ceph_inode_info *ci = ceph_inode(inode);
        struct ceph_mds_client *mdsc = ceph_sb_to_client(inode->i_sb)->mdsc;
        struct ceph_cap_flush *prealloc_cf = NULL;
+       struct ceph_buffer *old_blob = NULL;
        int issued;
        int err;
        int dirty = 0;
@@ -1109,13 +1115,15 @@ retry:
                struct ceph_buffer *blob;
 
                spin_unlock(&ci->i_ceph_lock);
-               dout(" preaallocating new blob size=%d\n", required_blob_size);
+               ceph_buffer_put(old_blob); /* Shouldn't be required */
+               dout(" pre-allocating new blob size=%d\n", required_blob_size);
                blob = ceph_buffer_new(required_blob_size, GFP_NOFS);
                if (!blob)
                        goto do_sync_unlocked;
                spin_lock(&ci->i_ceph_lock);
+               /* prealloc_blob can't be released while holding i_ceph_lock */
                if (ci->i_xattrs.prealloc_blob)
-                       ceph_buffer_put(ci->i_xattrs.prealloc_blob);
+                       old_blob = ci->i_xattrs.prealloc_blob;
                ci->i_xattrs.prealloc_blob = blob;
                goto retry;
        }
@@ -1131,6 +1139,7 @@ retry:
        }
 
        spin_unlock(&ci->i_ceph_lock);
+       ceph_buffer_put(old_blob);
        if (lock_snap_rwsem)
                up_read(&mdsc->snap_rwsem);
        if (dirty)
index a15a6e738eb5321dcde574c848f9a6435ffcd9aa..1795e80cbdf7b246c12f4bbdf758b14a1999d96a 100644 (file)
@@ -1113,7 +1113,7 @@ cifs_demultiplex_thread(void *p)
                mempool_resize(cifs_req_poolp, length + cifs_min_rcv);
 
        set_freezable();
-       allow_signal(SIGKILL);
+       allow_kernel_signal(SIGKILL);
        while (server->tcpStatus != CifsExiting) {
                if (try_to_freeze())
                        continue;
index 24bbe3cb7ad45e72b1cfca18c3084795d0be6a8c..cfb48bd088e12a0bbd8847e2b78e7ba14cb26fd8 100644 (file)
@@ -679,6 +679,13 @@ static void io_put_req(struct io_kiocb *req)
                io_free_req(req);
 }
 
+static unsigned io_cqring_events(struct io_cq_ring *ring)
+{
+       /* See comment at the top of this file */
+       smp_rmb();
+       return READ_ONCE(ring->r.tail) - READ_ONCE(ring->r.head);
+}
+
 /*
  * Find and free completed poll iocbs
  */
@@ -771,7 +778,7 @@ static int io_do_iopoll(struct io_ring_ctx *ctx, unsigned int *nr_events,
 static int io_iopoll_getevents(struct io_ring_ctx *ctx, unsigned int *nr_events,
                                long min)
 {
-       while (!list_empty(&ctx->poll_list)) {
+       while (!list_empty(&ctx->poll_list) && !need_resched()) {
                int ret;
 
                ret = io_do_iopoll(ctx, nr_events, min);
@@ -798,6 +805,12 @@ static void io_iopoll_reap_events(struct io_ring_ctx *ctx)
                unsigned int nr_events = 0;
 
                io_iopoll_getevents(ctx, &nr_events, 1);
+
+               /*
+                * Ensure we allow local-to-the-cpu processing to take place,
+                * in this case we need to ensure that we reap all events.
+                */
+               cond_resched();
        }
        mutex_unlock(&ctx->uring_lock);
 }
@@ -805,11 +818,42 @@ static void io_iopoll_reap_events(struct io_ring_ctx *ctx)
 static int io_iopoll_check(struct io_ring_ctx *ctx, unsigned *nr_events,
                           long min)
 {
-       int ret = 0;
+       int iters, ret = 0;
 
+       /*
+        * We disallow the app entering submit/complete with polling, but we
+        * still need to lock the ring to prevent racing with polled issue
+        * that got punted to a workqueue.
+        */
+       mutex_lock(&ctx->uring_lock);
+
+       iters = 0;
        do {
                int tmin = 0;
 
+               /*
+                * Don't enter poll loop if we already have events pending.
+                * If we do, we can potentially be spinning for commands that
+                * already triggered a CQE (eg in error).
+                */
+               if (io_cqring_events(ctx->cq_ring))
+                       break;
+
+               /*
+                * If a submit got punted to a workqueue, we can have the
+                * application entering polling for a command before it gets
+                * issued. That app will hold the uring_lock for the duration
+                * of the poll right here, so we need to take a breather every
+                * now and then to ensure that the issue has a chance to add
+                * the poll to the issued list. Otherwise we can spin here
+                * forever, while the workqueue is stuck trying to acquire the
+                * very same mutex.
+                */
+               if (!(++iters & 7)) {
+                       mutex_unlock(&ctx->uring_lock);
+                       mutex_lock(&ctx->uring_lock);
+               }
+
                if (*nr_events < min)
                        tmin = min - *nr_events;
 
@@ -819,6 +863,7 @@ static int io_iopoll_check(struct io_ring_ctx *ctx, unsigned *nr_events,
                ret = 0;
        } while (min && !*nr_events && !need_resched());
 
+       mutex_unlock(&ctx->uring_lock);
        return ret;
 }
 
@@ -2280,15 +2325,7 @@ static int io_sq_thread(void *data)
                        unsigned nr_events = 0;
 
                        if (ctx->flags & IORING_SETUP_IOPOLL) {
-                               /*
-                                * We disallow the app entering submit/complete
-                                * with polling, but we still need to lock the
-                                * ring to prevent racing with polled issue
-                                * that got punted to a workqueue.
-                                */
-                               mutex_lock(&ctx->uring_lock);
                                io_iopoll_check(ctx, &nr_events, 0);
-                               mutex_unlock(&ctx->uring_lock);
                        } else {
                                /*
                                 * Normal IO, just pretend everything completed.
@@ -2433,13 +2470,6 @@ static int io_ring_submit(struct io_ring_ctx *ctx, unsigned int to_submit)
        return submit;
 }
 
-static unsigned io_cqring_events(struct io_cq_ring *ring)
-{
-       /* See comment at the top of this file */
-       smp_rmb();
-       return READ_ONCE(ring->r.tail) - READ_ONCE(ring->r.head);
-}
-
 /*
  * Wait until events become available, if we don't already have some. The
  * application must reap them itself, as they reside on the shared cq ring.
@@ -3190,9 +3220,7 @@ SYSCALL_DEFINE6(io_uring_enter, unsigned int, fd, u32, to_submit,
                min_complete = min(min_complete, ctx->cq_entries);
 
                if (ctx->flags & IORING_SETUP_IOPOLL) {
-                       mutex_lock(&ctx->uring_lock);
                        ret = io_iopoll_check(ctx, &nr_events, min_complete);
-                       mutex_unlock(&ctx->uring_lock);
                } else {
                        ret = io_cqring_wait(ctx, min_complete, sig, sigsz);
                }
index 26ad75ae2be042d3372f3bea221a3af0787a4722..96352ab7bd8100af89f2fadfa50825e31221dd7b 100644 (file)
@@ -571,7 +571,7 @@ nfsd_cache_append(struct svc_rqst *rqstp, struct kvec *data)
  */
 static int nfsd_reply_cache_stats_show(struct seq_file *m, void *v)
 {
-       struct nfsd_net *nn = v;
+       struct nfsd_net *nn = m->private;
 
        seq_printf(m, "max entries:           %u\n", nn->max_drc_entries);
        seq_printf(m, "num entries:           %u\n",
index 13c548733860cca6414b23bc30caea2d64c69b02..3cf4f6aa48d605499b9b8b766084a50661e7d3a8 100644 (file)
@@ -1171,13 +1171,17 @@ static struct inode *nfsd_get_inode(struct super_block *sb, umode_t mode)
        return inode;
 }
 
-static int __nfsd_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
+static int __nfsd_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode, struct nfsdfs_client *ncl)
 {
        struct inode *inode;
 
        inode = nfsd_get_inode(dir->i_sb, mode);
        if (!inode)
                return -ENOMEM;
+       if (ncl) {
+               inode->i_private = ncl;
+               kref_get(&ncl->cl_ref);
+       }
        d_add(dentry, inode);
        inc_nlink(dir);
        fsnotify_mkdir(dir, dentry);
@@ -1194,17 +1198,14 @@ static struct dentry *nfsd_mkdir(struct dentry *parent, struct nfsdfs_client *nc
        dentry = d_alloc_name(parent, name);
        if (!dentry)
                goto out_err;
-       ret = __nfsd_mkdir(d_inode(parent), dentry, S_IFDIR | 0600);
+       ret = __nfsd_mkdir(d_inode(parent), dentry, S_IFDIR | 0600, ncl);
        if (ret)
                goto out_err;
-       if (ncl) {
-               d_inode(dentry)->i_private = ncl;
-               kref_get(&ncl->cl_ref);
-       }
 out:
        inode_unlock(dir);
        return dentry;
 out_err:
+       dput(dentry);
        dentry = ERR_PTR(ret);
        goto out;
 }
@@ -1214,11 +1215,9 @@ static void clear_ncl(struct inode *inode)
        struct nfsdfs_client *ncl = inode->i_private;
 
        inode->i_private = NULL;
-       synchronize_rcu();
        kref_put(&ncl->cl_ref, ncl->cl_release);
 }
 
-
 static struct nfsdfs_client *__get_nfsdfs_client(struct inode *inode)
 {
        struct nfsdfs_client *nc = inode->i_private;
@@ -1232,9 +1231,9 @@ struct nfsdfs_client *get_nfsdfs_client(struct inode *inode)
 {
        struct nfsdfs_client *nc;
 
-       rcu_read_lock();
+       inode_lock_shared(inode);
        nc = __get_nfsdfs_client(inode);
-       rcu_read_unlock();
+       inode_unlock_shared(inode);
        return nc;
 }
 /* from __rpc_unlink */
index 1f5088dec566b71a37f697edd7419b7813edbb4c..5bbf587f5bc135485d21331039a8085f1e0500f7 100644 (file)
@@ -1811,10 +1811,7 @@ static int generic_remap_check_len(struct inode *inode_in,
        return (remap_flags & REMAP_FILE_DEDUP) ? -EBADE : -EINVAL;
 }
 
-/*
- * Read a page's worth of file data into the page cache.  Return the page
- * locked.
- */
+/* Read a page's worth of file data into the page cache. */
 static struct page *vfs_dedupe_get_page(struct inode *inode, loff_t offset)
 {
        struct page *page;
@@ -1826,10 +1823,32 @@ static struct page *vfs_dedupe_get_page(struct inode *inode, loff_t offset)
                put_page(page);
                return ERR_PTR(-EIO);
        }
-       lock_page(page);
        return page;
 }
 
+/*
+ * Lock two pages, ensuring that we lock in offset order if the pages are from
+ * the same file.
+ */
+static void vfs_lock_two_pages(struct page *page1, struct page *page2)
+{
+       /* Always lock in order of increasing index. */
+       if (page1->index > page2->index)
+               swap(page1, page2);
+
+       lock_page(page1);
+       if (page1 != page2)
+               lock_page(page2);
+}
+
+/* Unlock two pages, being careful not to unlock the same page twice. */
+static void vfs_unlock_two_pages(struct page *page1, struct page *page2)
+{
+       unlock_page(page1);
+       if (page1 != page2)
+               unlock_page(page2);
+}
+
 /*
  * Compare extents of two files to see if they are the same.
  * Caller must have locked both inodes to prevent write races.
@@ -1867,10 +1886,24 @@ static int vfs_dedupe_file_range_compare(struct inode *src, loff_t srcoff,
                dest_page = vfs_dedupe_get_page(dest, destoff);
                if (IS_ERR(dest_page)) {
                        error = PTR_ERR(dest_page);
-                       unlock_page(src_page);
                        put_page(src_page);
                        goto out_error;
                }
+
+               vfs_lock_two_pages(src_page, dest_page);
+
+               /*
+                * Now that we've locked both pages, make sure they're still
+                * mapped to the file data we're interested in.  If not,
+                * someone is invalidating pages on us and we lose.
+                */
+               if (!PageUptodate(src_page) || !PageUptodate(dest_page) ||
+                   src_page->mapping != src->i_mapping ||
+                   dest_page->mapping != dest->i_mapping) {
+                       same = false;
+                       goto unlock;
+               }
+
                src_addr = kmap_atomic(src_page);
                dest_addr = kmap_atomic(dest_page);
 
@@ -1882,8 +1915,8 @@ static int vfs_dedupe_file_range_compare(struct inode *src, loff_t srcoff,
 
                kunmap_atomic(dest_addr);
                kunmap_atomic(src_addr);
-               unlock_page(dest_page);
-               unlock_page(src_page);
+unlock:
+               vfs_unlock_two_pages(src_page, dest_page);
                put_page(dest_page);
                put_page(src_page);
 
index 80d7301ab76d0c74a8b90cc9bee1c23aa9fbe24b..c0b84e960b20c138b1e3fe1cfe77c13f32a9428e 100644 (file)
@@ -51,7 +51,7 @@
 static void shrink_liability(struct ubifs_info *c, int nr_to_write)
 {
        down_read(&c->vfs_sb->s_umount);
-       writeback_inodes_sb(c->vfs_sb, WB_REASON_FS_FREE_SPACE);
+       writeback_inodes_sb_nr(c->vfs_sb, nr_to_write, WB_REASON_FS_FREE_SPACE);
        up_read(&c->vfs_sb->s_umount);
 }
 
index b52624e28fa1198b938f232322526861114c7be4..3b4b4114f208bfb6bdc1f94803e6d7b5b79bd372 100644 (file)
@@ -129,7 +129,6 @@ static void __orphan_drop(struct ubifs_info *c, struct ubifs_orphan *o)
 static void orphan_delete(struct ubifs_info *c, struct ubifs_orphan *orph)
 {
        if (orph->del) {
-               spin_unlock(&c->orphan_lock);
                dbg_gen("deleted twice ino %lu", orph->inum);
                return;
        }
@@ -138,7 +137,6 @@ static void orphan_delete(struct ubifs_info *c, struct ubifs_orphan *orph)
                orph->del = 1;
                orph->dnext = c->orph_dnext;
                c->orph_dnext = orph;
-               spin_unlock(&c->orphan_lock);
                dbg_gen("delete later ino %lu", orph->inum);
                return;
        }
index 2c0803b0ac3aa21190ca84ca65f59f2e5de1069b..8c1d571334bc82ff46e3d5da2e934df523c4a6c7 100644 (file)
@@ -609,6 +609,10 @@ static int init_constants_early(struct ubifs_info *c)
        c->max_bu_buf_len = UBIFS_MAX_BULK_READ * UBIFS_MAX_DATA_NODE_SZ;
        if (c->max_bu_buf_len > c->leb_size)
                c->max_bu_buf_len = c->leb_size;
+
+       /* Log is ready, preserve one LEB for commits. */
+       c->min_log_bytes = c->leb_size;
+
        return 0;
 }
 
index ccbdbd62f0d8ecf16a19f2f191d5809e317da9d5..fe6d804a38dc2d64b9397a6bf68e53b4c938f656 100644 (file)
@@ -880,6 +880,7 @@ static int userfaultfd_release(struct inode *inode, struct file *file)
        /* len == 0 means wake all */
        struct userfaultfd_wake_range range = { .len = 0, };
        unsigned long new_flags;
+       bool still_valid;
 
        WRITE_ONCE(ctx->released, true);
 
@@ -895,8 +896,7 @@ static int userfaultfd_release(struct inode *inode, struct file *file)
         * taking the mmap_sem for writing.
         */
        down_write(&mm->mmap_sem);
-       if (!mmget_still_valid(mm))
-               goto skip_mm;
+       still_valid = mmget_still_valid(mm);
        prev = NULL;
        for (vma = mm->mmap; vma; vma = vma->vm_next) {
                cond_resched();
@@ -907,19 +907,20 @@ static int userfaultfd_release(struct inode *inode, struct file *file)
                        continue;
                }
                new_flags = vma->vm_flags & ~(VM_UFFD_MISSING | VM_UFFD_WP);
-               prev = vma_merge(mm, prev, vma->vm_start, vma->vm_end,
-                                new_flags, vma->anon_vma,
-                                vma->vm_file, vma->vm_pgoff,
-                                vma_policy(vma),
-                                NULL_VM_UFFD_CTX);
-               if (prev)
-                       vma = prev;
-               else
-                       prev = vma;
+               if (still_valid) {
+                       prev = vma_merge(mm, prev, vma->vm_start, vma->vm_end,
+                                        new_flags, vma->anon_vma,
+                                        vma->vm_file, vma->vm_pgoff,
+                                        vma_policy(vma),
+                                        NULL_VM_UFFD_CTX);
+                       if (prev)
+                               vma = prev;
+                       else
+                               prev = vma;
+               }
                vma->vm_flags = new_flags;
                vma->vm_userfaultfd_ctx = NULL_VM_UFFD_CTX;
        }
-skip_mm:
        up_write(&mm->mmap_sem);
        mmput(mm);
 wakeup:
index 7fcf7569743f47a250f0bf2356f7c040b78cc59c..7bd7534f5051bb571fc1933df695d5405301c0b9 100644 (file)
@@ -547,63 +547,12 @@ xfs_file_compat_ioctl(
        struct inode            *inode = file_inode(filp);
        struct xfs_inode        *ip = XFS_I(inode);
        struct xfs_mount        *mp = ip->i_mount;
-       void                    __user *arg = (void __user *)p;
+       void                    __user *arg = compat_ptr(p);
        int                     error;
 
        trace_xfs_file_compat_ioctl(ip);
 
        switch (cmd) {
-       /* No size or alignment issues on any arch */
-       case XFS_IOC_DIOINFO:
-       case XFS_IOC_FSGEOMETRY_V4:
-       case XFS_IOC_FSGEOMETRY:
-       case XFS_IOC_AG_GEOMETRY:
-       case XFS_IOC_FSGETXATTR:
-       case XFS_IOC_FSSETXATTR:
-       case XFS_IOC_FSGETXATTRA:
-       case XFS_IOC_FSSETDM:
-       case XFS_IOC_GETBMAP:
-       case XFS_IOC_GETBMAPA:
-       case XFS_IOC_GETBMAPX:
-       case XFS_IOC_FSCOUNTS:
-       case XFS_IOC_SET_RESBLKS:
-       case XFS_IOC_GET_RESBLKS:
-       case XFS_IOC_FSGROWFSLOG:
-       case XFS_IOC_GOINGDOWN:
-       case XFS_IOC_ERROR_INJECTION:
-       case XFS_IOC_ERROR_CLEARALL:
-       case FS_IOC_GETFSMAP:
-       case XFS_IOC_SCRUB_METADATA:
-       case XFS_IOC_BULKSTAT:
-       case XFS_IOC_INUMBERS:
-               return xfs_file_ioctl(filp, cmd, p);
-#if !defined(BROKEN_X86_ALIGNMENT) || defined(CONFIG_X86_X32)
-       /*
-        * These are handled fine if no alignment issues.  To support x32
-        * which uses native 64-bit alignment we must emit these cases in
-        * addition to the ia-32 compat set below.
-        */
-       case XFS_IOC_ALLOCSP:
-       case XFS_IOC_FREESP:
-       case XFS_IOC_RESVSP:
-       case XFS_IOC_UNRESVSP:
-       case XFS_IOC_ALLOCSP64:
-       case XFS_IOC_FREESP64:
-       case XFS_IOC_RESVSP64:
-       case XFS_IOC_UNRESVSP64:
-       case XFS_IOC_FSGEOMETRY_V1:
-       case XFS_IOC_FSGROWFSDATA:
-       case XFS_IOC_FSGROWFSRT:
-       case XFS_IOC_ZERO_RANGE:
-#ifdef CONFIG_X86_X32
-       /*
-        * x32 special: this gets a different cmd number from the ia-32 compat
-        * case below; the associated data will match native 64-bit alignment.
-        */
-       case XFS_IOC_SWAPEXT:
-#endif
-               return xfs_file_ioctl(filp, cmd, p);
-#endif
 #if defined(BROKEN_X86_ALIGNMENT)
        case XFS_IOC_ALLOCSP_32:
        case XFS_IOC_FREESP_32:
@@ -705,6 +654,7 @@ xfs_file_compat_ioctl(
        case XFS_IOC_FSSETDM_BY_HANDLE_32:
                return xfs_compat_fssetdm_by_handle(filp, arg);
        default:
-               return -ENOIOCTLCMD;
+               /* try the native version */
+               return xfs_file_ioctl(filp, cmd, (unsigned long)arg);
        }
 }
index ff3c1fae53571e79d139e9117efc8ccc4ec751bd..fe285d123d69f1eb8c749ad145a02ea36c96904a 100644 (file)
@@ -793,6 +793,7 @@ xfs_setattr_nonsize(
 
 out_cancel:
        xfs_trans_cancel(tp);
+       xfs_iunlock(ip, XFS_ILOCK_EXCL);
 out_dqrele:
        xfs_qm_dqrele(udqp);
        xfs_qm_dqrele(gdqp);
index 0c954cad74493cf6fb9002b93101baeb7717e3f3..a339bd5fa260471428e27809808899c39ff949e0 100644 (file)
@@ -32,7 +32,7 @@ xfs_break_leased_layouts(
        struct xfs_inode        *ip = XFS_I(inode);
        int                     error;
 
-       while ((error = break_layout(inode, false) == -EWOULDBLOCK)) {
+       while ((error = break_layout(inode, false)) == -EWOULDBLOCK) {
                xfs_iunlock(ip, *iolock);
                *did_unlock = true;
                error = break_layout(inode, true);
index c4ec7afd1170a7550df8704b2bb71ae450c927f5..edbe37b7f636de145a0eeab9b837aee3120f3a77 100644 (file)
@@ -1190,11 +1190,11 @@ xfs_reflink_remap_blocks(
 }
 
 /*
- * Grab the exclusive iolock for a data copy from src to dest, making
- * sure to abide vfs locking order (lowest pointer value goes first) and
- * breaking the pnfs layout leases on dest before proceeding.  The loop
- * is needed because we cannot call the blocking break_layout() with the
- * src iolock held, and therefore have to back out both locks.
+ * Grab the exclusive iolock for a data copy from src to dest, making sure to
+ * abide vfs locking order (lowest pointer value goes first) and breaking the
+ * layout leases before proceeding.  The loop is needed because we cannot call
+ * the blocking break_layout() with the iolocks held, and therefore have to
+ * back out both locks.
  */
 static int
 xfs_iolock_two_inodes_and_break_layout(
@@ -1203,33 +1203,44 @@ xfs_iolock_two_inodes_and_break_layout(
 {
        int                     error;
 
-retry:
-       if (src < dest) {
-               inode_lock_shared(src);
-               inode_lock_nested(dest, I_MUTEX_NONDIR2);
-       } else {
-               /* src >= dest */
-               inode_lock(dest);
-       }
+       if (src > dest)
+               swap(src, dest);
 
-       error = break_layout(dest, false);
-       if (error == -EWOULDBLOCK) {
-               inode_unlock(dest);
-               if (src < dest)
-                       inode_unlock_shared(src);
+retry:
+       /* Wait to break both inodes' layouts before we start locking. */
+       error = break_layout(src, true);
+       if (error)
+               return error;
+       if (src != dest) {
                error = break_layout(dest, true);
                if (error)
                        return error;
-               goto retry;
        }
+
+       /* Lock one inode and make sure nobody got in and leased it. */
+       inode_lock(src);
+       error = break_layout(src, false);
        if (error) {
+               inode_unlock(src);
+               if (error == -EWOULDBLOCK)
+                       goto retry;
+               return error;
+       }
+
+       if (src == dest)
+               return 0;
+
+       /* Lock the other inode and make sure nobody got in and leased it. */
+       inode_lock_nested(dest, I_MUTEX_NONDIR2);
+       error = break_layout(dest, false);
+       if (error) {
+               inode_unlock(src);
                inode_unlock(dest);
-               if (src < dest)
-                       inode_unlock_shared(src);
+               if (error == -EWOULDBLOCK)
+                       goto retry;
                return error;
        }
-       if (src > dest)
-               inode_lock_shared_nested(src, I_MUTEX_NONDIR2);
+
        return 0;
 }
 
@@ -1247,10 +1258,10 @@ xfs_reflink_remap_unlock(
 
        xfs_iunlock(dest, XFS_MMAPLOCK_EXCL);
        if (!same_inode)
-               xfs_iunlock(src, XFS_MMAPLOCK_SHARED);
+               xfs_iunlock(src, XFS_MMAPLOCK_EXCL);
        inode_unlock(inode_out);
        if (!same_inode)
-               inode_unlock_shared(inode_in);
+               inode_unlock(inode_in);
 }
 
 /*
@@ -1325,7 +1336,7 @@ xfs_reflink_remap_prep(
        if (same_inode)
                xfs_ilock(src, XFS_MMAPLOCK_EXCL);
        else
-               xfs_lock_two_inodes(src, XFS_MMAPLOCK_SHARED, dest,
+               xfs_lock_two_inodes(src, XFS_MMAPLOCK_EXCL, dest,
                                XFS_MMAPLOCK_EXCL);
 
        /* Check file eligibility and prepare for block sharing. */
index 16a83959e616f114001f19870047787d2bb2eac4..42d573172e5396babc64bc0663e31562befa1c22 100644 (file)
@@ -95,9 +95,9 @@
 
 #define ACPI_DEFAULT_PAGE_SIZE          4096   /* Must be power of 2 */
 
-/* owner_id tracking. 8 entries allows for 255 owner_ids */
+/* owner_id tracking. 128 entries allows for 4095 owner_ids */
 
-#define ACPI_NUM_OWNERID_MASKS          8
+#define ACPI_NUM_OWNERID_MASKS          128
 
 /* Size of the root table array is increased by this increment */
 
index 1b59fb61f67d503725fb40d78763173ded00e412..2e63b7b390f5a77ed39901ad11f8b084565d7603 100644 (file)
@@ -330,6 +330,7 @@ acpi_status acpi_os_enter_sleep(u8 sleep_state, u32 rega_value, u32 regb_value);
  * Debug print routines
  */
 #ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_printf
+ACPI_PRINTF_LIKE(1)
 void ACPI_INTERNAL_VAR_XFACE acpi_os_printf(const char *format, ...);
 #endif
 
index 3845c8fcc94e5de64d09b679f61f5ce0eca5b45c..d66fc7cce6a712199786a966f2869922dd63fe30 100644 (file)
@@ -12,7 +12,7 @@
 
 /* Current ACPICA subsystem version in YYYYMMDD format */
 
-#define ACPI_CA_VERSION                 0x20190703
+#define ACPI_CA_VERSION                 0x20190816
 
 #include <acpi/acconfig.h>
 #include <acpi/actypes.h>
index ad6892a24015ee7fea303b163bc1d7f80e01dac9..2f3f28c7cea369a99c6ecab1847cc6feba129d5c 100644 (file)
@@ -442,8 +442,8 @@ typedef void *acpi_handle;  /* Actually a ptr to a NS Node */
 
 /* Owner IDs are used to track namespace nodes for selective deletion */
 
-typedef u8 acpi_owner_id;
-#define ACPI_OWNER_ID_MAX               0xFF
+typedef u16 acpi_owner_id;
+#define ACPI_OWNER_ID_MAX               0xFFF  /* 4095 possible owner IDs */
 
 #define ACPI_INTEGER_BIT_SIZE           64
 #define ACPI_MAX_DECIMAL_DIGITS         20     /* 2^64 = 18,446,744,073,709,551,616 */
@@ -506,7 +506,7 @@ typedef u64 acpi_integer;
 
 /* Pointer/Integer type conversions */
 
-#define ACPI_TO_POINTER(i)              ACPI_ADD_PTR (void, (void *) 0, (acpi_size) (i))
+#define ACPI_TO_POINTER(i)              ACPI_CAST_PTR (void, (acpi_size) (i))
 #define ACPI_TO_INTEGER(p)              ACPI_PTR_DIFF (p, (void *) 0)
 #define ACPI_OFFSET(d, f)               ACPI_PTR_DIFF (&(((d *) 0)->f), (void *) 0)
 #define ACPI_PHYSADDR_TO_PTR(i)         ACPI_TO_POINTER(i)
@@ -1265,12 +1265,14 @@ typedef enum {
 #define ACPI_OSI_WIN_VISTA_SP2          0x0A
 #define ACPI_OSI_WIN_7                  0x0B
 #define ACPI_OSI_WIN_8                  0x0C
-#define ACPI_OSI_WIN_10                 0x0D
-#define ACPI_OSI_WIN_10_RS1             0x0E
-#define ACPI_OSI_WIN_10_RS2             0x0F
-#define ACPI_OSI_WIN_10_RS3             0x10
-#define ACPI_OSI_WIN_10_RS4             0x11
-#define ACPI_OSI_WIN_10_RS5             0x12
+#define ACPI_OSI_WIN_8_1                0x0D
+#define ACPI_OSI_WIN_10                 0x0E
+#define ACPI_OSI_WIN_10_RS1             0x0F
+#define ACPI_OSI_WIN_10_RS2             0x10
+#define ACPI_OSI_WIN_10_RS3             0x11
+#define ACPI_OSI_WIN_10_RS4             0x12
+#define ACPI_OSI_WIN_10_RS5             0x13
+#define ACPI_OSI_WIN_10_19H1            0x14
 
 /* Definitions of getopt */
 
index 5e58bb29b1a36b55e86bf8951cd04eaf149853e5..11cdc7c60480f503aa510b5b54368ac66df45a86 100644 (file)
@@ -30,7 +30,8 @@ static inline struct ceph_buffer *ceph_buffer_get(struct ceph_buffer *b)
 
 static inline void ceph_buffer_put(struct ceph_buffer *b)
 {
-       kref_put(&b->kref, ceph_buffer_release);
+       if (b)
+               kref_put(&b->kref, ceph_buffer_release);
 }
 
 extern int ceph_decode_buffer(struct ceph_buffer **b, void **p, void *end);
index c05d4e661489b3625a2e83874cc87d4a51edf875..03f8e98e3bcc94b781bc66928d7e5e9c667dbe8b 100644 (file)
@@ -160,10 +160,7 @@ bool dma_release_from_contiguous(struct device *dev, struct page *pages,
 static inline struct page *dma_alloc_contiguous(struct device *dev, size_t size,
                gfp_t gfp)
 {
-       int node = dev ? dev_to_node(dev) : NUMA_NO_NODE;
-       size_t align = get_order(PAGE_ALIGN(size));
-
-       return alloc_pages_node(node, gfp, align);
+       return NULL;
 }
 
 static inline void dma_free_contiguous(struct device *dev, struct page *page,
index 40915b461f18d9179ed15efd57aed380b52392fa..f757a58191a6256368e9e0f7b17623b0500e2c0e 100644 (file)
@@ -241,30 +241,6 @@ static inline int irq_to_gpio(unsigned irq)
        return -EINVAL;
 }
 
-static inline int
-gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name,
-                      unsigned int gpio_offset, unsigned int pin_offset,
-                      unsigned int npins)
-{
-       WARN_ON(1);
-       return -EINVAL;
-}
-
-static inline int
-gpiochip_add_pingroup_range(struct gpio_chip *chip,
-                       struct pinctrl_dev *pctldev,
-                       unsigned int gpio_offset, const char *pin_group)
-{
-       WARN_ON(1);
-       return -EINVAL;
-}
-
-static inline void
-gpiochip_remove_pin_ranges(struct gpio_chip *chip)
-{
-       WARN_ON(1);
-}
-
 static inline int devm_gpio_request(struct device *dev, unsigned gpio,
                                    const char *label)
 {
index 91f391cd272e094d3d74683f08ac226fe8e1ce20..50028338a4cc081dc0f9dfcda8394804962dc1de 100644 (file)
@@ -94,11 +94,11 @@ struct keyring_index_key {
        union {
                struct {
 #ifdef __LITTLE_ENDIAN /* Put desc_len at the LSB of x */
-                       u     desc_len;
-                       char    desc[sizeof(long) - 1]; /* First few chars of description */
+                       u16     desc_len;
+                       char    desc[sizeof(long) - 2]; /* First few chars of description */
 #else
-                       char    desc[sizeof(long) - 1]; /* First few chars of description */
-                       u     desc_len;
+                       char    desc[sizeof(long) - 2]; /* First few chars of description */
+                       u16     desc_len;
 #endif
                };
                unsigned long x;
index ce9839c8bc1a6ca539628f078fc8bf7471a84ce7..c2f056b5766df377a02414c5081134b12688efa6 100644 (file)
@@ -446,11 +446,11 @@ enum {
 };
 
 enum {
-       MLX5_OPC_MOD_TLS_TIS_STATIC_PARAMS = 0x20,
+       MLX5_OPC_MOD_TLS_TIS_STATIC_PARAMS = 0x1,
 };
 
 enum {
-       MLX5_OPC_MOD_TLS_TIS_PROGRESS_PARAMS = 0x20,
+       MLX5_OPC_MOD_TLS_TIS_PROGRESS_PARAMS = 0x1,
 };
 
 enum {
index ec571fd7fcf89299e4ef17b17142fce13059de6e..b8b570c30b5ed967bd5acc38fe2e3f4a6c7025fa 100644 (file)
@@ -10054,9 +10054,8 @@ struct mlx5_ifc_tls_static_params_bits {
 };
 
 struct mlx5_ifc_tls_progress_params_bits {
-       u8         valid[0x1];
-       u8         reserved_at_1[0x7];
-       u8         pd[0x18];
+       u8         reserved_at_0[0x8];
+       u8         tisn[0x18];
 
        u8         next_record_tcp_sn[0x20];
 
index b5d99482d3fe18e5f9c2eceb606a75458ae7e969..1a5f88316b081463a4e76bb8b48aa312f75162d5 100644 (file)
@@ -282,6 +282,9 @@ extern void signal_setup_done(int failed, struct ksignal *ksig, int stepping);
 extern void exit_signals(struct task_struct *tsk);
 extern void kernel_sigaction(int, __sighandler_t);
 
+#define SIG_KTHREAD ((__force __sighandler_t)2)
+#define SIG_KTHREAD_KERNEL ((__force __sighandler_t)3)
+
 static inline void allow_signal(int sig)
 {
        /*
@@ -289,7 +292,17 @@ static inline void allow_signal(int sig)
         * know it'll be handled, so that they don't get converted to
         * SIGKILL or just silently dropped.
         */
-       kernel_sigaction(sig, (__force __sighandler_t)2);
+       kernel_sigaction(sig, SIG_KTHREAD);
+}
+
+static inline void allow_kernel_signal(int sig)
+{
+       /*
+        * Kernel threads handle their own signals. Let the signal code
+        * know signals sent by the kernel will be handled, so that they
+        * don't get silently dropped.
+        */
+       kernel_sigaction(sig, SIG_KTHREAD_KERNEL);
 }
 
 static inline void disallow_signal(int sig)
index d8af86d995d6fe0b7fe8afc3a21d7d8faac2d7ce..ba5583522d249444361314dc12ef63d5e6d5e79a 100644 (file)
@@ -1374,6 +1374,14 @@ static inline void skb_copy_hash(struct sk_buff *to, const struct sk_buff *from)
        to->l4_hash = from->l4_hash;
 };
 
+static inline void skb_copy_decrypted(struct sk_buff *to,
+                                     const struct sk_buff *from)
+{
+#ifdef CONFIG_TLS_DEVICE
+       to->decrypted = from->decrypted;
+#endif
+}
+
 #ifdef NET_SKBUFF_DATA_USES_OFFSET
 static inline unsigned char *skb_end_pointer(const struct sk_buff *skb)
 {
index 97523818cb14e0676cdc22c6b748f5b643ddc9ec..fc0bed59fc84ef8e6631d3c275853d52a46f84aa 100644 (file)
@@ -292,6 +292,9 @@ struct ucred {
 #define MSG_BATCH      0x40000 /* sendmmsg(): more messages coming */
 #define MSG_EOF         MSG_FIN
 #define MSG_NO_SHARED_FRAGS 0x80000 /* sendpage() internal : page frags are not shared */
+#define MSG_SENDPAGE_DECRYPTED 0x100000 /* sendpage() internal : page may carry
+                                         * plain text and require encryption
+                                         */
 
 #define MSG_ZEROCOPY   0x4000000       /* Use user data in kernel path */
 #define MSG_FASTOPEN   0x20000000      /* Send data in TCP SYN */
index 7acb953298a73118028ae04052fab9249529380f..84ff2844df2a8bc240b7186b7258fbef20c62940 100644 (file)
@@ -57,6 +57,7 @@ struct tk_read_base {
  * @cs_was_changed_seq:        The sequence number of clocksource change events
  * @next_leap_ktime:   CLOCK_MONOTONIC time value of a pending leap-second
  * @raw_sec:           CLOCK_MONOTONIC_RAW  time in seconds
+ * @monotonic_to_boot: CLOCK_MONOTONIC to CLOCK_BOOTTIME offset
  * @cycle_interval:    Number of clock cycles in one NTP interval
  * @xtime_interval:    Number of clock shifted nano seconds in one NTP
  *                     interval.
@@ -84,6 +85,9 @@ struct tk_read_base {
  *
  * wall_to_monotonic is no longer the boot time, getboottime must be
  * used instead.
+ *
+ * @monotonic_to_boottime is a timespec64 representation of @offs_boot to
+ * accelerate the VDSO update for CLOCK_BOOTTIME.
  */
 struct timekeeper {
        struct tk_read_base     tkr_mono;
@@ -99,6 +103,7 @@ struct timekeeper {
        u8                      cs_was_changed_seq;
        ktime_t                 next_leap_ktime;
        u64                     raw_sec;
+       struct timespec64       monotonic_to_boot;
 
        /* The following members are for timekeeping internal use */
        u64                     cycle_interval;
index ded574b32c2089c2140397a30d985ff7c1c550f0..ffc95b382eb56cac8b32ec2c022eb3a9e19159ad 100644 (file)
@@ -278,6 +278,7 @@ struct hci_dev {
        __u16           conn_info_min_age;
        __u16           conn_info_max_age;
        __u16           auth_payload_timeout;
+       __u8            min_enc_key_size;
        __u8            ssp_debug_mode;
        __u8            hw_error_code;
        __u32           clock;
index 010f26b31c89b375f4cabf6572d51f0383c93f0e..bac79e817776c6e65ed37f5b5c6af61a5df59ec0 100644 (file)
@@ -171,7 +171,7 @@ int inet_frag_queue_insert(struct inet_frag_queue *q, struct sk_buff *skb,
 void *inet_frag_reasm_prepare(struct inet_frag_queue *q, struct sk_buff *skb,
                              struct sk_buff *parent);
 void inet_frag_reasm_finish(struct inet_frag_queue *q, struct sk_buff *head,
-                           void *reasm_data);
+                           void *reasm_data, bool try_coalesce);
 struct sk_buff *inet_frag_pull_head(struct inet_frag_queue *q);
 
 #endif
index 4a9da951a794efbf9183c0a2e3d3ca94ec88f9d5..cb668bc2692db22e4639fcd3e95b21ed55f00410 100644 (file)
@@ -61,7 +61,6 @@ struct net {
        spinlock_t              rules_mod_lock;
 
        u32                     hash_mix;
-       atomic64_t              cookie_gen;
 
        struct list_head        list;           /* list of network namespaces */
        struct list_head        exit_list;      /* To linked to call pernet exit
index 9b624566b82d3028cd5210a183308e8571ade2e5..475d6f28ca677a8b40c106fa08af86971226000e 100644 (file)
@@ -421,8 +421,7 @@ struct nft_set {
        unsigned char                   *udata;
        /* runtime data below here */
        const struct nft_set_ops        *ops ____cacheline_aligned;
-       u16                             flags:13,
-                                       bound:1,
+       u16                             flags:14,
                                        genmask:2;
        u8                              klen;
        u8                              dlen;
@@ -1348,12 +1347,15 @@ struct nft_trans_rule {
 struct nft_trans_set {
        struct nft_set                  *set;
        u32                             set_id;
+       bool                            bound;
 };
 
 #define nft_trans_set(trans)   \
        (((struct nft_trans_set *)trans->data)->set)
 #define nft_trans_set_id(trans)        \
        (((struct nft_trans_set *)trans->data)->set_id)
+#define nft_trans_set_bound(trans)     \
+       (((struct nft_trans_set *)trans->data)->bound)
 
 struct nft_trans_chain {
        bool                            update;
@@ -1384,12 +1386,15 @@ struct nft_trans_table {
 struct nft_trans_elem {
        struct nft_set                  *set;
        struct nft_set_elem             elem;
+       bool                            bound;
 };
 
 #define nft_trans_elem_set(trans)      \
        (((struct nft_trans_elem *)trans->data)->set)
 #define nft_trans_elem(trans)  \
        (((struct nft_trans_elem *)trans->data)->elem)
+#define nft_trans_elem_set_bound(trans)        \
+       (((struct nft_trans_elem *)trans->data)->bound)
 
 struct nft_trans_obj {
        struct nft_object               *obj;
index 3196663a10e30e24880f571fb59a30e2e2cabfb7..c8b9dec376f56599a7403718727b0674681fbcdb 100644 (file)
@@ -73,4 +73,6 @@ int nft_flow_rule_offload_commit(struct net *net);
        (__reg)->key            = __key;                                \
        memset(&(__reg)->mask, 0xff, (__reg)->len);
 
+int nft_chain_offload_priority(struct nft_base_chain *basechain);
+
 #endif
index e4650e5b64a1db760a220fba3b7d4ad50eb54b17..b140c8f1be22d2e9943d7d98ae9e7db3c076f20b 100644 (file)
@@ -684,9 +684,8 @@ static inline int nlmsg_parse(const struct nlmsghdr *nlh, int hdrlen,
                              const struct nla_policy *policy,
                              struct netlink_ext_ack *extack)
 {
-       return __nla_parse(tb, maxtype, nlmsg_attrdata(nlh, hdrlen),
-                          nlmsg_attrlen(nlh, hdrlen), policy,
-                          NL_VALIDATE_STRICT, extack);
+       return __nlmsg_parse(nlh, hdrlen, tb, maxtype, policy,
+                            NL_VALIDATE_STRICT, extack);
 }
 
 /**
index e429809ca90d84b167749195126b0c8004d5223c..98be18ef1ed3400739120e354ba1c5082bc94770 100644 (file)
@@ -646,7 +646,7 @@ tc_cls_common_offload_init(struct flow_cls_common_offload *cls_common,
 {
        cls_common->chain_index = tp->chain->index;
        cls_common->protocol = tp->protocol;
-       cls_common->prio = tp->prio;
+       cls_common->prio = tp->prio >> 16;
        if (tc_skip_sw(flags) || flags & TCA_CLS_FLAGS_VERBOSE)
                cls_common->extack = extack;
 }
index 228db3998e46e42156fec16e78f5e627669a9687..2c53f1a1d905409247b1bdafdfaf99d86e430cd0 100644 (file)
@@ -2482,6 +2482,7 @@ static inline bool sk_fullsock(const struct sock *sk)
 
 /* Checks if this SKB belongs to an HW offloaded socket
  * and whether any SW fallbacks are required based on dev.
+ * Check decrypted mark in case skb_orphan() cleared socket.
  */
 static inline struct sk_buff *sk_validate_xmit_skb(struct sk_buff *skb,
                                                   struct net_device *dev)
@@ -2489,8 +2490,15 @@ static inline struct sk_buff *sk_validate_xmit_skb(struct sk_buff *skb,
 #ifdef CONFIG_SOCK_VALIDATE_XMIT
        struct sock *sk = skb->sk;
 
-       if (sk && sk_fullsock(sk) && sk->sk_validate_xmit_skb)
+       if (sk && sk_fullsock(sk) && sk->sk_validate_xmit_skb) {
                skb = sk->sk_validate_xmit_skb(sk, dev, skb);
+#ifdef CONFIG_TLS_DEVICE
+       } else if (unlikely(skb->decrypted)) {
+               pr_warn_ratelimited("unencrypted skb with no associated socket - dropping\n");
+               kfree_skb(skb);
+               skb = NULL;
+#endif
+       }
 #endif
 
        return skb;
index b0fc6b26bdf531f8a42bf3b398d1d32b6bb6d2e2..83df1ec6664eabbffd851976093a578a5b57177a 100644 (file)
@@ -105,8 +105,7 @@ struct rdma_restrack_entry {
 };
 
 int rdma_restrack_count(struct ib_device *dev,
-                       enum rdma_restrack_type type,
-                       struct pid_namespace *ns);
+                       enum rdma_restrack_type type);
 
 void rdma_restrack_kadd(struct rdma_restrack_entry *res);
 void rdma_restrack_uadd(struct rdma_restrack_entry *res);
index cc1d060cbf133e92460cf91f24c35babccbd9248..fa06b528c73c51d14f757be9328470d987e1945f 100644 (file)
@@ -498,10 +498,10 @@ rxrpc_tx_points;
 #define E_(a, b)       { a, b }
 
 TRACE_EVENT(rxrpc_local,
-           TP_PROTO(struct rxrpc_local *local, enum rxrpc_local_trace op,
+           TP_PROTO(unsigned int local_debug_id, enum rxrpc_local_trace op,
                     int usage, const void *where),
 
-           TP_ARGS(local, op, usage, where),
+           TP_ARGS(local_debug_id, op, usage, where),
 
            TP_STRUCT__entry(
                    __field(unsigned int,       local           )
@@ -511,7 +511,7 @@ TRACE_EVENT(rxrpc_local,
                             ),
 
            TP_fast_assign(
-                   __entry->local = local->debug_id;
+                   __entry->local = local_debug_id;
                    __entry->op = op;
                    __entry->usage = usage;
                    __entry->where = where;
index fa1c753dcdbc7f170a65dbaa8b01683de5e6e942..a5aa7d3ac6a116a7a8d3c08d840c37a70e42e7a4 100644 (file)
@@ -1466,8 +1466,8 @@ union bpf_attr {
  *             If no cookie has been set yet, generate a new cookie. Once
  *             generated, the socket cookie remains stable for the life of the
  *             socket. This helper can be useful for monitoring per socket
- *             networking traffic statistics as it provides a unique socket
- *             identifier per namespace.
+ *             networking traffic statistics as it provides a global socket
+ *             identifier that can be assumed unique.
  *     Return
  *             A 8-byte long non-decreasing number on success, or 0 if the
  *             socket field is missing inside *skb*.
index a18b719f49d4dfbbb978270f791fe992cfc8b2a9..784ba0b9690af31b0419e07e1b0cb2261bad5e68 100644 (file)
 
 #define JFFS2_ACL_VERSION              0x0001
 
-// Maybe later...
-//#define JFFS2_NODETYPE_CHECKPOINT (JFFS2_FEATURE_RWCOMPAT_DELETE | JFFS2_NODE_ACCURATE | 3)
-//#define JFFS2_NODETYPE_OPTIONS (JFFS2_FEATURE_RWCOMPAT_COPY | JFFS2_NODE_ACCURATE | 4)
-
-
 #define JFFS2_INO_FLAG_PREREAD   1     /* Do read_inode() for this one at
                                           mount time, don't wait for it to
                                           happen later */
index 2bd410f934b3241179a4162a9817ecef0132759c..69cfb4345388c3f55a9ebef8df15fe9794bc7269 100644 (file)
@@ -230,9 +230,7 @@ bool dma_release_from_contiguous(struct device *dev, struct page *pages,
  */
 struct page *dma_alloc_contiguous(struct device *dev, size_t size, gfp_t gfp)
 {
-       int node = dev ? dev_to_node(dev) : NUMA_NO_NODE;
-       size_t count = PAGE_ALIGN(size) >> PAGE_SHIFT;
-       size_t align = get_order(PAGE_ALIGN(size));
+       size_t count = size >> PAGE_SHIFT;
        struct page *page = NULL;
        struct cma *cma = NULL;
 
@@ -243,14 +241,12 @@ struct page *dma_alloc_contiguous(struct device *dev, size_t size, gfp_t gfp)
 
        /* CMA can be used only in the context which permits sleeping */
        if (cma && gfpflags_allow_blocking(gfp)) {
+               size_t align = get_order(size);
                size_t cma_align = min_t(size_t, align, CONFIG_CMA_ALIGNMENT);
 
                page = cma_alloc(cma, count, cma_align, gfp & __GFP_NOWARN);
        }
 
-       /* Fallback allocation of normal pages */
-       if (!page)
-               page = alloc_pages_node(node, gfp, align);
        return page;
 }
 
index 795c9b095d7573a79df1d4eeef00a10dca6a2ee4..706113c6bebc3d984d0e5abe4acf83519cbec13b 100644 (file)
@@ -85,6 +85,8 @@ static bool dma_coherent_ok(struct device *dev, phys_addr_t phys, size_t size)
 struct page *__dma_direct_alloc_pages(struct device *dev, size_t size,
                dma_addr_t *dma_handle, gfp_t gfp, unsigned long attrs)
 {
+       size_t alloc_size = PAGE_ALIGN(size);
+       int node = dev_to_node(dev);
        struct page *page = NULL;
        u64 phys_mask;
 
@@ -95,8 +97,14 @@ struct page *__dma_direct_alloc_pages(struct device *dev, size_t size,
        gfp &= ~__GFP_ZERO;
        gfp |= __dma_direct_optimal_gfp_mask(dev, dev->coherent_dma_mask,
                        &phys_mask);
+       page = dma_alloc_contiguous(dev, alloc_size, gfp);
+       if (page && !dma_coherent_ok(dev, page_to_phys(page), size)) {
+               dma_free_contiguous(dev, page, alloc_size);
+               page = NULL;
+       }
 again:
-       page = dma_alloc_contiguous(dev, size, gfp);
+       if (!page)
+               page = alloc_pages_node(node, gfp, get_order(alloc_size));
        if (page && !dma_coherent_ok(dev, page_to_phys(page), size)) {
                dma_free_contiguous(dev, page, size);
                page = NULL;
index 9484e88dabc28d8e532a9465f45180c340aed4cd..9be995fc3c5a1414593056b09757db62efb15557 100644 (file)
@@ -295,6 +295,18 @@ static void irq_sysfs_add(int irq, struct irq_desc *desc)
        }
 }
 
+static void irq_sysfs_del(struct irq_desc *desc)
+{
+       /*
+        * If irq_sysfs_init() has not yet been invoked (early boot), then
+        * irq_kobj_base is NULL and the descriptor was never added.
+        * kobject_del() complains about a object with no parent, so make
+        * it conditional.
+        */
+       if (irq_kobj_base)
+               kobject_del(&desc->kobj);
+}
+
 static int __init irq_sysfs_init(void)
 {
        struct irq_desc *desc;
@@ -325,6 +337,7 @@ static struct kobj_type irq_kobj_type = {
 };
 
 static void irq_sysfs_add(int irq, struct irq_desc *desc) {}
+static void irq_sysfs_del(struct irq_desc *desc) {}
 
 #endif /* CONFIG_SYSFS */
 
@@ -438,7 +451,7 @@ static void free_desc(unsigned int irq)
         * The sysfs entry must be serialized against a concurrent
         * irq_sysfs_init() as well.
         */
-       kobject_del(&desc->kobj);
+       irq_sysfs_del(desc);
        delete_irq_desc(irq);
 
        /*
index 9873fc627d61f14295545817547aa4b96f7a00eb..d9770a5393c89925d2fa3f391dfb341a34a70409 100644 (file)
@@ -470,6 +470,7 @@ static DECLARE_DELAYED_WORK(optimizing_work, kprobe_optimizer);
  */
 static void do_optimize_kprobes(void)
 {
+       lockdep_assert_held(&text_mutex);
        /*
         * The optimization/unoptimization refers online_cpus via
         * stop_machine() and cpu-hotplug modifies online_cpus.
@@ -487,9 +488,7 @@ static void do_optimize_kprobes(void)
            list_empty(&optimizing_list))
                return;
 
-       mutex_lock(&text_mutex);
        arch_optimize_kprobes(&optimizing_list);
-       mutex_unlock(&text_mutex);
 }
 
 /*
@@ -500,6 +499,7 @@ static void do_unoptimize_kprobes(void)
 {
        struct optimized_kprobe *op, *tmp;
 
+       lockdep_assert_held(&text_mutex);
        /* See comment in do_optimize_kprobes() */
        lockdep_assert_cpus_held();
 
@@ -507,7 +507,6 @@ static void do_unoptimize_kprobes(void)
        if (list_empty(&unoptimizing_list))
                return;
 
-       mutex_lock(&text_mutex);
        arch_unoptimize_kprobes(&unoptimizing_list, &freeing_list);
        /* Loop free_list for disarming */
        list_for_each_entry_safe(op, tmp, &freeing_list, list) {
@@ -524,7 +523,6 @@ static void do_unoptimize_kprobes(void)
                } else
                        list_del_init(&op->list);
        }
-       mutex_unlock(&text_mutex);
 }
 
 /* Reclaim all kprobes on the free_list */
@@ -556,6 +554,7 @@ static void kprobe_optimizer(struct work_struct *work)
 {
        mutex_lock(&kprobe_mutex);
        cpus_read_lock();
+       mutex_lock(&text_mutex);
        /* Lock modules while optimizing kprobes */
        mutex_lock(&module_mutex);
 
@@ -583,6 +582,7 @@ static void kprobe_optimizer(struct work_struct *work)
        do_free_cleaned_kprobes();
 
        mutex_unlock(&module_mutex);
+       mutex_unlock(&text_mutex);
        cpus_read_unlock();
        mutex_unlock(&kprobe_mutex);
 
index 5933395af9a0c18c7ccf1f97543d15050e1550a0..9ee93421269c061393f03721bcbf1a94239f1877 100644 (file)
@@ -65,9 +65,9 @@
 /*
  * Modules' sections will be aligned on page boundaries
  * to ensure complete separation of code and data, but
- * only when CONFIG_STRICT_MODULE_RWX=y
+ * only when CONFIG_ARCH_HAS_STRICT_MODULE_RWX=y
  */
-#ifdef CONFIG_STRICT_MODULE_RWX
+#ifdef CONFIG_ARCH_HAS_STRICT_MODULE_RWX
 # define debug_align(X) ALIGN(X, PAGE_SIZE)
 #else
 # define debug_align(X) (X)
index 2b037f1954732ab5a3b5bca3ecc7bd4a638774bc..010d578118d62760a9fd388dd5c236dd3fb632fc 100644 (file)
@@ -3904,7 +3904,7 @@ void __noreturn do_task_dead(void)
 
 static inline void sched_submit_work(struct task_struct *tsk)
 {
-       if (!tsk->state || tsk_is_pi_blocked(tsk))
+       if (!tsk->state)
                return;
 
        /*
@@ -3920,6 +3920,9 @@ static inline void sched_submit_work(struct task_struct *tsk)
                preempt_enable_no_resched();
        }
 
+       if (tsk_is_pi_blocked(tsk))
+               return;
+
        /*
         * If we are going to sleep and we have plugged IO queued,
         * make sure to submit it to avoid deadlocks.
index 23fbbcc414d5d739507ac1f8ecb5757c87a9ce55..6e52b67b420e7a3312f463f8d3bb6baad6576041 100644 (file)
@@ -1131,7 +1131,15 @@ static void psi_trigger_destroy(struct kref *ref)
         * deadlock while waiting for psi_poll_work to acquire trigger_lock
         */
        if (kworker_to_destroy) {
+               /*
+                * After the RCU grace period has expired, the worker
+                * can no longer be found through group->poll_kworker.
+                * But it might have been already scheduled before
+                * that - deschedule it cleanly before destroying it.
+                */
                kthread_cancel_delayed_work_sync(&group->poll_work);
+               atomic_set(&group->poll_scheduled, 0);
+
                kthread_destroy_worker(kworker_to_destroy);
        }
        kfree(t);
index e667be6907d71333c44546cd43ebfdde6c9eab3c..534fec266a334b299846034e878c271619fe5c71 100644 (file)
@@ -90,6 +90,11 @@ static bool sig_task_ignored(struct task_struct *t, int sig, bool force)
            handler == SIG_DFL && !(force && sig_kernel_only(sig)))
                return true;
 
+       /* Only allow kernel generated signals to this kthread */
+       if (unlikely((t->flags & PF_KTHREAD) &&
+                    (handler == SIG_KTHREAD_KERNEL) && !force))
+               return true;
+
        return sig_handler_ignored(handler, sig);
 }
 
index d911c8470149e87330838153abfd511f868fe383..ca69290bee2a3131358993e9a3bbc32c6a9a9231 100644 (file)
@@ -146,6 +146,11 @@ static void tk_set_wall_to_mono(struct timekeeper *tk, struct timespec64 wtm)
 static inline void tk_update_sleep_time(struct timekeeper *tk, ktime_t delta)
 {
        tk->offs_boot = ktime_add(tk->offs_boot, delta);
+       /*
+        * Timespec representation for VDSO update to avoid 64bit division
+        * on every update.
+        */
+       tk->monotonic_to_boot = ktime_to_timespec64(tk->offs_boot);
 }
 
 /*
index 8cf3596a4ce677ca787e214d6f33b32a6d6b4088..4bc37ac3bb0526994e2dcacd20369e6f2e98f8d3 100644 (file)
@@ -17,7 +17,7 @@ static inline void update_vdso_data(struct vdso_data *vdata,
                                    struct timekeeper *tk)
 {
        struct vdso_timestamp *vdso_ts;
-       u64 nsec;
+       u64 nsec, sec;
 
        vdata[CS_HRES_COARSE].cycle_last        = tk->tkr_mono.cycle_last;
        vdata[CS_HRES_COARSE].mask              = tk->tkr_mono.mask;
@@ -45,23 +45,27 @@ static inline void update_vdso_data(struct vdso_data *vdata,
        }
        vdso_ts->nsec   = nsec;
 
-       /* CLOCK_MONOTONIC_RAW */
-       vdso_ts         = &vdata[CS_RAW].basetime[CLOCK_MONOTONIC_RAW];
-       vdso_ts->sec    = tk->raw_sec;
-       vdso_ts->nsec   = tk->tkr_raw.xtime_nsec;
+       /* Copy MONOTONIC time for BOOTTIME */
+       sec     = vdso_ts->sec;
+       /* Add the boot offset */
+       sec     += tk->monotonic_to_boot.tv_sec;
+       nsec    += (u64)tk->monotonic_to_boot.tv_nsec << tk->tkr_mono.shift;
 
        /* CLOCK_BOOTTIME */
        vdso_ts         = &vdata[CS_HRES_COARSE].basetime[CLOCK_BOOTTIME];
-       vdso_ts->sec    = tk->xtime_sec + tk->wall_to_monotonic.tv_sec;
-       nsec = tk->tkr_mono.xtime_nsec;
-       nsec += ((u64)(tk->wall_to_monotonic.tv_nsec +
-                      ktime_to_ns(tk->offs_boot)) << tk->tkr_mono.shift);
+       vdso_ts->sec    = sec;
+
        while (nsec >= (((u64)NSEC_PER_SEC) << tk->tkr_mono.shift)) {
                nsec -= (((u64)NSEC_PER_SEC) << tk->tkr_mono.shift);
                vdso_ts->sec++;
        }
        vdso_ts->nsec   = nsec;
 
+       /* CLOCK_MONOTONIC_RAW */
+       vdso_ts         = &vdata[CS_RAW].basetime[CLOCK_MONOTONIC_RAW];
+       vdso_ts->sec    = tk->raw_sec;
+       vdso_ts->nsec   = tk->tkr_raw.xtime_nsec;
+
        /* CLOCK_TAI */
        vdso_ts         = &vdata[CS_HRES_COARSE].basetime[CLOCK_TAI];
        vdso_ts->sec    = tk->xtime_sec + (s64)tk->tai_offset;
index 738065f765abd4dda88a9f762736f9a1108cb6fd..de1f15969e2782edd648a43fc5e7c6d7edacb38b 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/shmem_fs.h>
 #include <linux/oom.h>
 #include <linux/numa.h>
+#include <linux/page_owner.h>
 
 #include <asm/tlb.h>
 #include <asm/pgalloc.h>
@@ -2516,6 +2517,9 @@ static void __split_huge_page(struct page *page, struct list_head *list,
        }
 
        ClearPageCompound(head);
+
+       split_page_owner(head, HPAGE_PMD_ORDER);
+
        /* See comment in __split_huge_page_tail() */
        if (PageAnon(head)) {
                /* Additional pin to swap cache */
index 2277b82902d83a75fabfb9c2c2269315a6022b71..95d16a42db6bc731e11c9e86bb639bb277cc345d 100644 (file)
@@ -407,8 +407,14 @@ static inline bool shadow_invalid(u8 tag, s8 shadow_byte)
        if (IS_ENABLED(CONFIG_KASAN_GENERIC))
                return shadow_byte < 0 ||
                        shadow_byte >= KASAN_SHADOW_SCALE_SIZE;
-       else
-               return tag != (u8)shadow_byte;
+
+       /* else CONFIG_KASAN_SW_TAGS: */
+       if ((u8)shadow_byte == KASAN_TAG_INVALID)
+               return true;
+       if ((tag != KASAN_TAG_KERNEL) && (tag != (u8)shadow_byte))
+               return true;
+
+       return false;
 }
 
 static bool __kasan_slab_free(struct kmem_cache *cache, void *object,
index 6f5c0c517c497dbddad9016ef2d1993e4e1bcf05..26e2999af608d3776e609b213d522345fc793792 100644 (file)
@@ -3260,6 +3260,60 @@ static u64 mem_cgroup_read_u64(struct cgroup_subsys_state *css,
        }
 }
 
+static void memcg_flush_percpu_vmstats(struct mem_cgroup *memcg)
+{
+       unsigned long stat[MEMCG_NR_STAT];
+       struct mem_cgroup *mi;
+       int node, cpu, i;
+
+       for (i = 0; i < MEMCG_NR_STAT; i++)
+               stat[i] = 0;
+
+       for_each_online_cpu(cpu)
+               for (i = 0; i < MEMCG_NR_STAT; i++)
+                       stat[i] += raw_cpu_read(memcg->vmstats_percpu->stat[i]);
+
+       for (mi = memcg; mi; mi = parent_mem_cgroup(mi))
+               for (i = 0; i < MEMCG_NR_STAT; i++)
+                       atomic_long_add(stat[i], &mi->vmstats[i]);
+
+       for_each_node(node) {
+               struct mem_cgroup_per_node *pn = memcg->nodeinfo[node];
+               struct mem_cgroup_per_node *pi;
+
+               for (i = 0; i < NR_VM_NODE_STAT_ITEMS; i++)
+                       stat[i] = 0;
+
+               for_each_online_cpu(cpu)
+                       for (i = 0; i < NR_VM_NODE_STAT_ITEMS; i++)
+                               stat[i] += raw_cpu_read(
+                                       pn->lruvec_stat_cpu->count[i]);
+
+               for (pi = pn; pi; pi = parent_nodeinfo(pi, node))
+                       for (i = 0; i < NR_VM_NODE_STAT_ITEMS; i++)
+                               atomic_long_add(stat[i], &pi->lruvec_stat[i]);
+       }
+}
+
+static void memcg_flush_percpu_vmevents(struct mem_cgroup *memcg)
+{
+       unsigned long events[NR_VM_EVENT_ITEMS];
+       struct mem_cgroup *mi;
+       int cpu, i;
+
+       for (i = 0; i < NR_VM_EVENT_ITEMS; i++)
+               events[i] = 0;
+
+       for_each_online_cpu(cpu)
+               for (i = 0; i < NR_VM_EVENT_ITEMS; i++)
+                       events[i] += raw_cpu_read(
+                               memcg->vmstats_percpu->events[i]);
+
+       for (mi = memcg; mi; mi = parent_mem_cgroup(mi))
+               for (i = 0; i < NR_VM_EVENT_ITEMS; i++)
+                       atomic_long_add(events[i], &mi->vmevents[i]);
+}
+
 #ifdef CONFIG_MEMCG_KMEM
 static int memcg_online_kmem(struct mem_cgroup *memcg)
 {
@@ -4682,6 +4736,12 @@ static void __mem_cgroup_free(struct mem_cgroup *memcg)
 {
        int node;
 
+       /*
+        * Flush percpu vmstats and vmevents to guarantee the value correctness
+        * on parent's and all ancestor levels.
+        */
+       memcg_flush_percpu_vmstats(memcg);
+       memcg_flush_percpu_vmevents(memcg);
        for_each_node(node)
                free_mem_cgroup_per_node_info(memcg, node);
        free_percpu(memcg->vmstats_percpu);
index 272c6de1bf4ead31c22aca202940da00bc8eaf8b..9c9194959271cfc0d9214bf60bb09b96c5b1a96a 100644 (file)
@@ -2238,27 +2238,12 @@ static int move_freepages(struct zone *zone,
        unsigned int order;
        int pages_moved = 0;
 
-#ifndef CONFIG_HOLES_IN_ZONE
-       /*
-        * page_zone is not safe to call in this context when
-        * CONFIG_HOLES_IN_ZONE is set. This bug check is probably redundant
-        * anyway as we check zone boundaries in move_freepages_block().
-        * Remove at a later date when no bug reports exist related to
-        * grouping pages by mobility
-        */
-       VM_BUG_ON(pfn_valid(page_to_pfn(start_page)) &&
-                 pfn_valid(page_to_pfn(end_page)) &&
-                 page_zone(start_page) != page_zone(end_page));
-#endif
        for (page = start_page; page <= end_page;) {
                if (!pfn_valid_within(page_to_pfn(page))) {
                        page++;
                        continue;
                }
 
-               /* Make sure we are not inadvertently changing nodes */
-               VM_BUG_ON_PAGE(page_to_nid(page) != zone_to_nid(zone), page);
-
                if (!PageBuddy(page)) {
                        /*
                         * We assume that pages that could be isolated for
@@ -2273,6 +2258,10 @@ static int move_freepages(struct zone *zone,
                        continue;
                }
 
+               /* Make sure we are not inadvertently changing nodes */
+               VM_BUG_ON_PAGE(page_to_nid(page) != zone_to_nid(zone), page);
+               VM_BUG_ON_PAGE(page_zone(page) != zone, page);
+
                order = page_order(page);
                move_to_free_area(page, &zone->free_area[order], migratetype);
                page += 1 << order;
index ed19d98c9dcd1641c5e66d27d586e93f43fadce1..e31cd9bd4ed561bcf4f6788da18f4759c7f61b96 100644 (file)
@@ -41,6 +41,7 @@
 #include <linux/workqueue.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
+#include <linux/wait.h>
 #include <linux/zpool.h>
 #include <linux/magic.h>
 
@@ -145,6 +146,8 @@ struct z3fold_header {
  * @release_wq:        workqueue for safe page release
  * @work:      work_struct for safe page release
  * @inode:     inode for z3fold pseudo filesystem
+ * @destroying: bool to stop migration once we start destruction
+ * @isolated: int to count the number of pages currently in isolation
  *
  * This structure is allocated at pool creation time and maintains metadata
  * pertaining to a particular z3fold pool.
@@ -163,8 +166,11 @@ struct z3fold_pool {
        const struct zpool_ops *zpool_ops;
        struct workqueue_struct *compact_wq;
        struct workqueue_struct *release_wq;
+       struct wait_queue_head isolate_wait;
        struct work_struct work;
        struct inode *inode;
+       bool destroying;
+       int isolated;
 };
 
 /*
@@ -769,6 +775,7 @@ static struct z3fold_pool *z3fold_create_pool(const char *name, gfp_t gfp,
                goto out_c;
        spin_lock_init(&pool->lock);
        spin_lock_init(&pool->stale_lock);
+       init_waitqueue_head(&pool->isolate_wait);
        pool->unbuddied = __alloc_percpu(sizeof(struct list_head)*NCHUNKS, 2);
        if (!pool->unbuddied)
                goto out_pool;
@@ -808,6 +815,15 @@ out:
        return NULL;
 }
 
+static bool pool_isolated_are_drained(struct z3fold_pool *pool)
+{
+       bool ret;
+
+       spin_lock(&pool->lock);
+       ret = pool->isolated == 0;
+       spin_unlock(&pool->lock);
+       return ret;
+}
 /**
  * z3fold_destroy_pool() - destroys an existing z3fold pool
  * @pool:      the z3fold pool to be destroyed
@@ -817,6 +833,22 @@ out:
 static void z3fold_destroy_pool(struct z3fold_pool *pool)
 {
        kmem_cache_destroy(pool->c_handle);
+       /*
+        * We set pool-> destroying under lock to ensure that
+        * z3fold_page_isolate() sees any changes to destroying. This way we
+        * avoid the need for any memory barriers.
+        */
+
+       spin_lock(&pool->lock);
+       pool->destroying = true;
+       spin_unlock(&pool->lock);
+
+       /*
+        * We need to ensure that no pages are being migrated while we destroy
+        * these workqueues, as migration can queue work on either of the
+        * workqueues.
+        */
+       wait_event(pool->isolate_wait, !pool_isolated_are_drained(pool));
 
        /*
         * We need to destroy pool->compact_wq before pool->release_wq,
@@ -1307,6 +1339,28 @@ static u64 z3fold_get_pool_size(struct z3fold_pool *pool)
        return atomic64_read(&pool->pages_nr);
 }
 
+/*
+ * z3fold_dec_isolated() expects to be called while pool->lock is held.
+ */
+static void z3fold_dec_isolated(struct z3fold_pool *pool)
+{
+       assert_spin_locked(&pool->lock);
+       VM_BUG_ON(pool->isolated <= 0);
+       pool->isolated--;
+
+       /*
+        * If we have no more isolated pages, we have to see if
+        * z3fold_destroy_pool() is waiting for a signal.
+        */
+       if (pool->isolated == 0 && waitqueue_active(&pool->isolate_wait))
+               wake_up_all(&pool->isolate_wait);
+}
+
+static void z3fold_inc_isolated(struct z3fold_pool *pool)
+{
+       pool->isolated++;
+}
+
 static bool z3fold_page_isolate(struct page *page, isolate_mode_t mode)
 {
        struct z3fold_header *zhdr;
@@ -1333,6 +1387,33 @@ static bool z3fold_page_isolate(struct page *page, isolate_mode_t mode)
                spin_lock(&pool->lock);
                if (!list_empty(&page->lru))
                        list_del(&page->lru);
+               /*
+                * We need to check for destruction while holding pool->lock, as
+                * otherwise destruction could see 0 isolated pages, and
+                * proceed.
+                */
+               if (unlikely(pool->destroying)) {
+                       spin_unlock(&pool->lock);
+                       /*
+                        * If this page isn't stale, somebody else holds a
+                        * reference to it. Let't drop our refcount so that they
+                        * can call the release logic.
+                        */
+                       if (unlikely(kref_put(&zhdr->refcount,
+                                             release_z3fold_page_locked))) {
+                               /*
+                                * If we get here we have kref problems, so we
+                                * should freak out.
+                                */
+                               WARN(1, "Z3fold is experiencing kref problems\n");
+                               return false;
+                       }
+                       z3fold_page_unlock(zhdr);
+                       return false;
+               }
+
+
+               z3fold_inc_isolated(pool);
                spin_unlock(&pool->lock);
                z3fold_page_unlock(zhdr);
                return true;
@@ -1401,6 +1482,10 @@ static int z3fold_page_migrate(struct address_space *mapping, struct page *newpa
 
        queue_work_on(new_zhdr->cpu, pool->compact_wq, &new_zhdr->work);
 
+       spin_lock(&pool->lock);
+       z3fold_dec_isolated(pool);
+       spin_unlock(&pool->lock);
+
        page_mapcount_reset(page);
        put_page(page);
        return 0;
@@ -1420,10 +1505,14 @@ static void z3fold_page_putback(struct page *page)
        INIT_LIST_HEAD(&page->lru);
        if (kref_put(&zhdr->refcount, release_z3fold_page_locked)) {
                atomic64_dec(&pool->pages_nr);
+               spin_lock(&pool->lock);
+               z3fold_dec_isolated(pool);
+               spin_unlock(&pool->lock);
                return;
        }
        spin_lock(&pool->lock);
        list_add(&page->lru, &pool->lru);
+       z3fold_dec_isolated(pool);
        spin_unlock(&pool->lock);
        z3fold_page_unlock(zhdr);
 }
index 57fbb7ced69f3a47111db0f665ec05b26e4186db..08def3a0d2007c3030384e4cd4d04f83b5ac7c74 100644 (file)
@@ -54,6 +54,7 @@
 #include <linux/mount.h>
 #include <linux/pseudo_fs.h>
 #include <linux/migrate.h>
+#include <linux/wait.h>
 #include <linux/pagemap.h>
 #include <linux/fs.h>
 
@@ -268,6 +269,10 @@ struct zs_pool {
 #ifdef CONFIG_COMPACTION
        struct inode *inode;
        struct work_struct free_work;
+       /* A wait queue for when migration races with async_free_zspage() */
+       struct wait_queue_head migration_wait;
+       atomic_long_t isolated_pages;
+       bool destroying;
 #endif
 };
 
@@ -1862,6 +1867,31 @@ static void dec_zspage_isolation(struct zspage *zspage)
        zspage->isolated--;
 }
 
+static void putback_zspage_deferred(struct zs_pool *pool,
+                                   struct size_class *class,
+                                   struct zspage *zspage)
+{
+       enum fullness_group fg;
+
+       fg = putback_zspage(class, zspage);
+       if (fg == ZS_EMPTY)
+               schedule_work(&pool->free_work);
+
+}
+
+static inline void zs_pool_dec_isolated(struct zs_pool *pool)
+{
+       VM_BUG_ON(atomic_long_read(&pool->isolated_pages) <= 0);
+       atomic_long_dec(&pool->isolated_pages);
+       /*
+        * There's no possibility of racing, since wait_for_isolated_drain()
+        * checks the isolated count under &class->lock after enqueuing
+        * on migration_wait.
+        */
+       if (atomic_long_read(&pool->isolated_pages) == 0 && pool->destroying)
+               wake_up_all(&pool->migration_wait);
+}
+
 static void replace_sub_page(struct size_class *class, struct zspage *zspage,
                                struct page *newpage, struct page *oldpage)
 {
@@ -1931,6 +1961,7 @@ static bool zs_page_isolate(struct page *page, isolate_mode_t mode)
         */
        if (!list_empty(&zspage->list) && !is_zspage_isolated(zspage)) {
                get_zspage_mapping(zspage, &class_idx, &fullness);
+               atomic_long_inc(&pool->isolated_pages);
                remove_zspage(class, zspage, fullness);
        }
 
@@ -2030,8 +2061,16 @@ static int zs_page_migrate(struct address_space *mapping, struct page *newpage,
         * Page migration is done so let's putback isolated zspage to
         * the list if @page is final isolated subpage in the zspage.
         */
-       if (!is_zspage_isolated(zspage))
-               putback_zspage(class, zspage);
+       if (!is_zspage_isolated(zspage)) {
+               /*
+                * We cannot race with zs_destroy_pool() here because we wait
+                * for isolation to hit zero before we start destroying.
+                * Also, we ensure that everyone can see pool->destroying before
+                * we start waiting.
+                */
+               putback_zspage_deferred(pool, class, zspage);
+               zs_pool_dec_isolated(pool);
+       }
 
        reset_page(page);
        put_page(page);
@@ -2077,13 +2116,12 @@ static void zs_page_putback(struct page *page)
        spin_lock(&class->lock);
        dec_zspage_isolation(zspage);
        if (!is_zspage_isolated(zspage)) {
-               fg = putback_zspage(class, zspage);
                /*
                 * Due to page_lock, we cannot free zspage immediately
                 * so let's defer.
                 */
-               if (fg == ZS_EMPTY)
-                       schedule_work(&pool->free_work);
+               putback_zspage_deferred(pool, class, zspage);
+               zs_pool_dec_isolated(pool);
        }
        spin_unlock(&class->lock);
 }
@@ -2107,8 +2145,36 @@ static int zs_register_migration(struct zs_pool *pool)
        return 0;
 }
 
+static bool pool_isolated_are_drained(struct zs_pool *pool)
+{
+       return atomic_long_read(&pool->isolated_pages) == 0;
+}
+
+/* Function for resolving migration */
+static void wait_for_isolated_drain(struct zs_pool *pool)
+{
+
+       /*
+        * We're in the process of destroying the pool, so there are no
+        * active allocations. zs_page_isolate() fails for completely free
+        * zspages, so we need only wait for the zs_pool's isolated
+        * count to hit zero.
+        */
+       wait_event(pool->migration_wait,
+                  pool_isolated_are_drained(pool));
+}
+
 static void zs_unregister_migration(struct zs_pool *pool)
 {
+       pool->destroying = true;
+       /*
+        * We need a memory barrier here to ensure global visibility of
+        * pool->destroying. Thus pool->isolated pages will either be 0 in which
+        * case we don't care, or it will be > 0 and pool->destroying will
+        * ensure that we wake up once isolation hits 0.
+        */
+       smp_mb();
+       wait_for_isolated_drain(pool); /* This can block */
        flush_work(&pool->free_work);
        iput(pool->inode);
 }
@@ -2346,6 +2412,8 @@ struct zs_pool *zs_create_pool(const char *name)
        if (!pool->name)
                goto err;
 
+       init_waitqueue_head(&pool->migration_wait);
+
        if (create_cache(pool))
                goto err;
 
index 67d7f83009ae1e0c1fc8e9e694d3d33a9f93d7d5..1d5bdf3a4b65526c7c4b90283d97366e10ba19c3 100644 (file)
@@ -2303,7 +2303,7 @@ __batadv_mcast_flags_dump(struct sk_buff *msg, u32 portid,
 
        while (bucket_tmp < hash->size) {
                if (batadv_mcast_flags_dump_bucket(msg, portid, cb, hash,
-                                                  *bucket, &idx_tmp))
+                                                  bucket_tmp, &idx_tmp))
                        break;
 
                bucket_tmp++;
@@ -2420,8 +2420,10 @@ void batadv_mcast_purge_orig(struct batadv_orig_node *orig)
        batadv_mcast_want_unsnoop_update(bat_priv, orig, BATADV_NO_FLAGS);
        batadv_mcast_want_ipv4_update(bat_priv, orig, BATADV_NO_FLAGS);
        batadv_mcast_want_ipv6_update(bat_priv, orig, BATADV_NO_FLAGS);
-       batadv_mcast_want_rtr4_update(bat_priv, orig, BATADV_NO_FLAGS);
-       batadv_mcast_want_rtr6_update(bat_priv, orig, BATADV_NO_FLAGS);
+       batadv_mcast_want_rtr4_update(bat_priv, orig,
+                                     BATADV_MCAST_WANT_NO_RTR4);
+       batadv_mcast_want_rtr6_update(bat_priv, orig,
+                                     BATADV_MCAST_WANT_NO_RTR6);
 
        spin_unlock_bh(&orig->mcast_handler_lock);
 }
index b9585e7d9d2e9492b0d495ae58b8da9029bce6b7..04bc79359a1736b28e83f0eb88828ceefd430f25 100644 (file)
@@ -3202,6 +3202,7 @@ struct hci_dev *hci_alloc_dev(void)
        hdev->conn_info_min_age = DEFAULT_CONN_INFO_MIN_AGE;
        hdev->conn_info_max_age = DEFAULT_CONN_INFO_MAX_AGE;
        hdev->auth_payload_timeout = DEFAULT_AUTH_PAYLOAD_TIMEOUT;
+       hdev->min_enc_key_size = HCI_MIN_ENC_KEY_SIZE;
 
        mutex_init(&hdev->lock);
        mutex_init(&hdev->req_lock);
index bb67f4a5479a2c79d724956c883d80e2a0c93345..402e2cc54044acc3ec7243915a177affdb004c14 100644 (file)
@@ -433,6 +433,35 @@ static int auto_accept_delay_set(void *data, u64 val)
        return 0;
 }
 
+static int min_encrypt_key_size_set(void *data, u64 val)
+{
+       struct hci_dev *hdev = data;
+
+       if (val < 1 || val > 16)
+               return -EINVAL;
+
+       hci_dev_lock(hdev);
+       hdev->min_enc_key_size = val;
+       hci_dev_unlock(hdev);
+
+       return 0;
+}
+
+static int min_encrypt_key_size_get(void *data, u64 *val)
+{
+       struct hci_dev *hdev = data;
+
+       hci_dev_lock(hdev);
+       *val = hdev->min_enc_key_size;
+       hci_dev_unlock(hdev);
+
+       return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(min_encrypt_key_size_fops,
+                       min_encrypt_key_size_get,
+                       min_encrypt_key_size_set, "%llu\n");
+
 static int auto_accept_delay_get(void *data, u64 *val)
 {
        struct hci_dev *hdev = data;
@@ -545,6 +574,8 @@ void hci_debugfs_create_bredr(struct hci_dev *hdev)
        if (lmp_ssp_capable(hdev)) {
                debugfs_create_file("ssp_debug_mode", 0444, hdev->debugfs,
                                    hdev, &ssp_debug_mode_fops);
+               debugfs_create_file("min_encrypt_key_size", 0644, hdev->debugfs,
+                                   hdev, &min_encrypt_key_size_fops);
                debugfs_create_file("auto_accept_delay", 0644, hdev->debugfs,
                                    hdev, &auto_accept_delay_fops);
        }
index 5abd423b55fa9c3839eb37d412c16a8735f901a5..8d889969ae7edaf2acf653098aaae0d98618776b 100644 (file)
@@ -101,6 +101,7 @@ static int hidp_send_message(struct hidp_session *session, struct socket *sock,
 {
        struct sk_buff *skb;
        struct sock *sk = sock->sk;
+       int ret;
 
        BT_DBG("session %p data %p size %d", session, data, size);
 
@@ -114,13 +115,17 @@ static int hidp_send_message(struct hidp_session *session, struct socket *sock,
        }
 
        skb_put_u8(skb, hdr);
-       if (data && size > 0)
+       if (data && size > 0) {
                skb_put_data(skb, data, size);
+               ret = size;
+       } else {
+               ret = 0;
+       }
 
        skb_queue_tail(transmit, skb);
        wake_up_interruptible(sk_sleep(sk));
 
-       return 0;
+       return ret;
 }
 
 static int hidp_send_ctrl_message(struct hidp_session *session,
index cc506fe99b4d7e092eefd90f9ea41bce9297dfca..dfc1edb168b78b2ed43575cdd6087c45b75a0f82 100644 (file)
@@ -1361,7 +1361,7 @@ static bool l2cap_check_enc_key_size(struct hci_conn *hcon)
         * actually encrypted before enforcing a key size.
         */
        return (!test_bit(HCI_CONN_ENCRYPT, &hcon->flags) ||
-               hcon->enc_key_size >= HCI_MIN_ENC_KEY_SIZE);
+               hcon->enc_key_size >= hcon->hdev->min_enc_key_size);
 }
 
 static void l2cap_do_start(struct l2cap_chan *chan)
index 0b2df09b25549265cc40888b0757b94afefe68a5..78ae6e8c953d03427535ea26732d125ed9432531 100644 (file)
@@ -1496,7 +1496,7 @@ static enum calc_target_result calc_target(struct ceph_osd_client *osdc,
        struct ceph_osds up, acting;
        bool force_resend = false;
        bool unpaused = false;
-       bool legacy_change;
+       bool legacy_change = false;
        bool split = false;
        bool sort_bitwise = ceph_osdmap_flag(osdc, CEPH_OSDMAP_SORTBITWISE);
        bool recovery_deletes = ceph_osdmap_flag(osdc,
@@ -1584,15 +1584,14 @@ static enum calc_target_result calc_target(struct ceph_osd_client *osdc,
                t->osd = acting.primary;
        }
 
-       if (unpaused || legacy_change || force_resend ||
-           (split && con && CEPH_HAVE_FEATURE(con->peer_features,
-                                              RESEND_ON_SPLIT)))
+       if (unpaused || legacy_change || force_resend || split)
                ct_res = CALC_TARGET_NEED_RESEND;
        else
                ct_res = CALC_TARGET_NO_ACTION;
 
 out:
-       dout("%s t %p -> ct_res %d osd %d\n", __func__, t, ct_res, t->osd);
+       dout("%s t %p -> %d%d%d%d ct_res %d osd%d\n", __func__, t, unpaused,
+            legacy_change, force_resend, split, ct_res, t->osd);
        return ct_res;
 }
 
index d57b0cc995a0cea45d82bf73d8149aae9f7b2e17..6d08553f885cdb44ed3e53c2231abb7f48bf309c 100644 (file)
@@ -1992,6 +1992,19 @@ void skb_set_owner_w(struct sk_buff *skb, struct sock *sk)
 }
 EXPORT_SYMBOL(skb_set_owner_w);
 
+static bool can_skb_orphan_partial(const struct sk_buff *skb)
+{
+#ifdef CONFIG_TLS_DEVICE
+       /* Drivers depend on in-order delivery for crypto offload,
+        * partial orphan breaks out-of-order-OK logic.
+        */
+       if (skb->decrypted)
+               return false;
+#endif
+       return (skb->destructor == sock_wfree ||
+               (IS_ENABLED(CONFIG_INET) && skb->destructor == tcp_wfree));
+}
+
 /* This helper is used by netem, as it can hold packets in its
  * delay queue. We want to allow the owner socket to send more
  * packets, as if they were already TX completed by a typical driver.
@@ -2003,11 +2016,7 @@ void skb_orphan_partial(struct sk_buff *skb)
        if (skb_is_tcp_pure_ack(skb))
                return;
 
-       if (skb->destructor == sock_wfree
-#ifdef CONFIG_INET
-           || skb->destructor == tcp_wfree
-#endif
-               ) {
+       if (can_skb_orphan_partial(skb)) {
                struct sock *sk = skb->sk;
 
                if (refcount_inc_not_zero(&sk->sk_refcnt)) {
index 3312a5849a974e372a49164abca8f7067a2ed7e7..c13ffbd33d8d6ad4f591571325aaee321df5b242 100644 (file)
@@ -19,6 +19,7 @@ static const struct sock_diag_handler *sock_diag_handlers[AF_MAX];
 static int (*inet_rcv_compat)(struct sk_buff *skb, struct nlmsghdr *nlh);
 static DEFINE_MUTEX(sock_diag_table_mutex);
 static struct workqueue_struct *broadcast_wq;
+static atomic64_t cookie_gen;
 
 u64 sock_gen_cookie(struct sock *sk)
 {
@@ -27,7 +28,7 @@ u64 sock_gen_cookie(struct sock *sk)
 
                if (res)
                        return res;
-               res = atomic64_inc_return(&sock_net(sk)->cookie_gen);
+               res = atomic64_inc_return(&cookie_gen);
                atomic64_cmpxchg(&sk->sk_cookie, 0, res);
        }
 }
index 4ec5b7f85d51ea2274b69e0ae68fa824fac2edde..09d9286b27ccb9fb215f3bafb0511d49dfaa1062 100644 (file)
@@ -153,6 +153,9 @@ static void dsa_switch_mdb_add_bitmap(struct dsa_switch *ds,
 {
        int port;
 
+       if (!ds->ops->port_mdb_add)
+               return;
+
        for_each_set_bit(port, bitmap, ds->num_ports)
                ds->ops->port_mdb_add(ds, port, mdb);
 }
index e4aba5d485be6a59c639a23b75172f5015c4280f..bbe9b3b2d3959fef28d1d94a0bcc0a71077d607d 100644 (file)
@@ -170,7 +170,7 @@ static int lowpan_frag_reasm(struct lowpan_frag_queue *fq, struct sk_buff *skb,
        reasm_data = inet_frag_reasm_prepare(&fq->q, skb, prev_tail);
        if (!reasm_data)
                goto out_oom;
-       inet_frag_reasm_finish(&fq->q, skb, reasm_data);
+       inet_frag_reasm_finish(&fq->q, skb, reasm_data, false);
 
        skb->dev = ldev;
        skb->tstamp = fq->q.stamp;
index a999451345f9805a195915dc2c55a9db31a51002..10d31733297d7358b55b45d64bc447039365df1d 100644 (file)
@@ -475,11 +475,12 @@ void *inet_frag_reasm_prepare(struct inet_frag_queue *q, struct sk_buff *skb,
 EXPORT_SYMBOL(inet_frag_reasm_prepare);
 
 void inet_frag_reasm_finish(struct inet_frag_queue *q, struct sk_buff *head,
-                           void *reasm_data)
+                           void *reasm_data, bool try_coalesce)
 {
        struct sk_buff **nextp = (struct sk_buff **)reasm_data;
        struct rb_node *rbn;
        struct sk_buff *fp;
+       int sum_truesize;
 
        skb_push(head, head->data - skb_network_header(head));
 
@@ -487,25 +488,41 @@ void inet_frag_reasm_finish(struct inet_frag_queue *q, struct sk_buff *head,
        fp = FRAG_CB(head)->next_frag;
        rbn = rb_next(&head->rbnode);
        rb_erase(&head->rbnode, &q->rb_fragments);
+
+       sum_truesize = head->truesize;
        while (rbn || fp) {
                /* fp points to the next sk_buff in the current run;
                 * rbn points to the next run.
                 */
                /* Go through the current run. */
                while (fp) {
-                       *nextp = fp;
-                       nextp = &fp->next;
-                       fp->prev = NULL;
-                       memset(&fp->rbnode, 0, sizeof(fp->rbnode));
-                       fp->sk = NULL;
-                       head->data_len += fp->len;
-                       head->len += fp->len;
+                       struct sk_buff *next_frag = FRAG_CB(fp)->next_frag;
+                       bool stolen;
+                       int delta;
+
+                       sum_truesize += fp->truesize;
                        if (head->ip_summed != fp->ip_summed)
                                head->ip_summed = CHECKSUM_NONE;
                        else if (head->ip_summed == CHECKSUM_COMPLETE)
                                head->csum = csum_add(head->csum, fp->csum);
-                       head->truesize += fp->truesize;
-                       fp = FRAG_CB(fp)->next_frag;
+
+                       if (try_coalesce && skb_try_coalesce(head, fp, &stolen,
+                                                            &delta)) {
+                               kfree_skb_partial(fp, stolen);
+                       } else {
+                               fp->prev = NULL;
+                               memset(&fp->rbnode, 0, sizeof(fp->rbnode));
+                               fp->sk = NULL;
+
+                               head->data_len += fp->len;
+                               head->len += fp->len;
+                               head->truesize += fp->truesize;
+
+                               *nextp = fp;
+                               nextp = &fp->next;
+                       }
+
+                       fp = next_frag;
                }
                /* Move to the next run. */
                if (rbn) {
@@ -516,7 +533,7 @@ void inet_frag_reasm_finish(struct inet_frag_queue *q, struct sk_buff *head,
                        rbn = rbnext;
                }
        }
-       sub_frag_mem_limit(q->fqdir, head->truesize);
+       sub_frag_mem_limit(q->fqdir, sum_truesize);
 
        *nextp = NULL;
        skb_mark_not_on_list(head);
index 4385eb9e781ffc017a65d166ddf12c11fc901c0e..cfeb8890f94ee95b2246ba98beb338a33fc45d1d 100644 (file)
@@ -393,6 +393,11 @@ err:
        return err;
 }
 
+static bool ip_frag_coalesce_ok(const struct ipq *qp)
+{
+       return qp->q.key.v4.user == IP_DEFRAG_LOCAL_DELIVER;
+}
+
 /* Build a new IP datagram from all its fragments. */
 static int ip_frag_reasm(struct ipq *qp, struct sk_buff *skb,
                         struct sk_buff *prev_tail, struct net_device *dev)
@@ -421,7 +426,8 @@ static int ip_frag_reasm(struct ipq *qp, struct sk_buff *skb,
        if (len > 65535)
                goto out_oversize;
 
-       inet_frag_reasm_finish(&qp->q, skb, reasm_data);
+       inet_frag_reasm_finish(&qp->q, skb, reasm_data,
+                              ip_frag_coalesce_ok(qp));
 
        skb->dev = dev;
        IPCB(skb)->frag_max_size = max(qp->max_df_size, qp->q.max_size);
index 776905899ac06bcbaa7ece1f580303478e736d56..77b485d60b9d0e00edc4e2f0d6c5bb3a9460b23b 100644 (file)
@@ -984,6 +984,9 @@ new_segment:
                        if (!skb)
                                goto wait_for_memory;
 
+#ifdef CONFIG_TLS_DEVICE
+                       skb->decrypted = !!(flags & MSG_SENDPAGE_DECRYPTED);
+#endif
                        skb_entail(sk, skb);
                        copy = size_goal;
                }
index 3d1e1540138440a0c0f6a65aabd888626ad0e384..8a56e09cfb0ed3ebf03795ae4b5d1eb3f04221ba 100644 (file)
@@ -398,10 +398,14 @@ more_data:
 static int tcp_bpf_sendmsg(struct sock *sk, struct msghdr *msg, size_t size)
 {
        struct sk_msg tmp, *msg_tx = NULL;
-       int flags = msg->msg_flags | MSG_NO_SHARED_FRAGS;
        int copied = 0, err = 0;
        struct sk_psock *psock;
        long timeo;
+       int flags;
+
+       /* Don't let internal do_tcp_sendpages() flags through */
+       flags = (msg->msg_flags & ~MSG_SENDPAGE_DECRYPTED);
+       flags |= MSG_NO_SHARED_FRAGS;
 
        psock = sk_psock_get(sk);
        if (unlikely(!psock))
index 6e4afc48d7bba7cded4d3fe38f32ab02328f9e05..979520e46e33c16ba2237cb36ef7b4dab94f6546 100644 (file)
@@ -1320,6 +1320,7 @@ int tcp_fragment(struct sock *sk, enum tcp_queue tcp_queue,
        buff = sk_stream_alloc_skb(sk, nsize, gfp, true);
        if (!buff)
                return -ENOMEM; /* We'll just try again later. */
+       skb_copy_decrypted(buff, skb);
 
        sk->sk_wmem_queued += buff->truesize;
        sk_mem_charge(sk, buff->truesize);
@@ -1874,6 +1875,7 @@ static int tso_fragment(struct sock *sk, struct sk_buff *skb, unsigned int len,
        buff = sk_stream_alloc_skb(sk, 0, gfp, true);
        if (unlikely(!buff))
                return -ENOMEM;
+       skb_copy_decrypted(buff, skb);
 
        sk->sk_wmem_queued += buff->truesize;
        sk_mem_charge(sk, buff->truesize);
@@ -2143,6 +2145,7 @@ static int tcp_mtu_probe(struct sock *sk)
        sk_mem_charge(sk, nskb->truesize);
 
        skb = tcp_send_head(sk);
+       skb_copy_decrypted(nskb, skb);
 
        TCP_SKB_CB(nskb)->seq = TCP_SKB_CB(skb)->seq;
        TCP_SKB_CB(nskb)->end_seq = TCP_SKB_CB(skb)->seq + probe_size;
index 0f82c150543b75f42c35f0199244a3a8cf5dd3f7..fed9666a2f7da13cd2d686b71a1454401a18b7b4 100644 (file)
@@ -348,7 +348,7 @@ static int nf_ct_frag6_reasm(struct frag_queue *fq, struct sk_buff *skb,
 
        skb_reset_transport_header(skb);
 
-       inet_frag_reasm_finish(&fq->q, skb, reasm_data);
+       inet_frag_reasm_finish(&fq->q, skb, reasm_data, false);
 
        skb->ignore_df = 1;
        skb->dev = dev;
index ca05b16f1bb95d4122a79fa9759011fd204f3e6f..1f5d4d196dccee12ee979f305b1b904864ff246e 100644 (file)
@@ -282,7 +282,7 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff *skb,
 
        skb_reset_transport_header(skb);
 
-       inet_frag_reasm_finish(&fq->q, skb, reasm_data);
+       inet_frag_reasm_finish(&fq->q, skb, reasm_data, true);
 
        skb->dev = dev;
        ipv6_hdr(skb)->payload_len = htons(payload_len);
index a542761e90d1fc269efbce6e4222da4b562b1c8e..81a8ef42b88d3893a210bea4f03b6eb4cbf04f99 100644 (file)
@@ -453,13 +453,12 @@ EXPORT_SYMBOL_GPL(nf_ct_invert_tuple);
  * table location, we assume id gets exposed to userspace.
  *
  * Following nf_conn items do not change throughout lifetime
- * of the nf_conn after it has been committed to main hash table:
+ * of the nf_conn:
  *
  * 1. nf_conn address
- * 2. nf_conn->ext address
- * 3. nf_conn->master address (normally NULL)
- * 4. tuple
- * 5. the associated net namespace
+ * 2. nf_conn->master address (normally NULL)
+ * 3. the associated net namespace
+ * 4. the original direction tuple
  */
 u32 nf_ct_get_id(const struct nf_conn *ct)
 {
@@ -469,9 +468,10 @@ u32 nf_ct_get_id(const struct nf_conn *ct)
        net_get_random_once(&ct_id_seed, sizeof(ct_id_seed));
 
        a = (unsigned long)ct;
-       b = (unsigned long)ct->master ^ net_hash_mix(nf_ct_net(ct));
-       c = (unsigned long)ct->ext;
-       d = (unsigned long)siphash(&ct->tuplehash, sizeof(ct->tuplehash),
+       b = (unsigned long)ct->master;
+       c = (unsigned long)nf_ct_net(ct);
+       d = (unsigned long)siphash(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple,
+                                  sizeof(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple),
                                   &ct_id_seed);
 #ifdef CONFIG_64BIT
        return siphash_4u64((u64)a, (u64)b, (u64)c, (u64)d, &ct_id_seed);
index e3d797252a981cdc7e3362be0e157c6db1d429a1..80a8f9ae4c93118d651f6b27f97f1f89bda77cfe 100644 (file)
@@ -111,15 +111,16 @@ static void flow_offload_fixup_tcp(struct ip_ct_tcp *tcp)
 #define NF_FLOWTABLE_TCP_PICKUP_TIMEOUT        (120 * HZ)
 #define NF_FLOWTABLE_UDP_PICKUP_TIMEOUT        (30 * HZ)
 
-static void flow_offload_fixup_ct_state(struct nf_conn *ct)
+static inline __s32 nf_flow_timeout_delta(unsigned int timeout)
+{
+       return (__s32)(timeout - (u32)jiffies);
+}
+
+static void flow_offload_fixup_ct_timeout(struct nf_conn *ct)
 {
        const struct nf_conntrack_l4proto *l4proto;
+       int l4num = nf_ct_protonum(ct);
        unsigned int timeout;
-       int l4num;
-
-       l4num = nf_ct_protonum(ct);
-       if (l4num == IPPROTO_TCP)
-               flow_offload_fixup_tcp(&ct->proto.tcp);
 
        l4proto = nf_ct_l4proto_find(l4num);
        if (!l4proto)
@@ -132,7 +133,20 @@ static void flow_offload_fixup_ct_state(struct nf_conn *ct)
        else
                return;
 
-       ct->timeout = nfct_time_stamp + timeout;
+       if (nf_flow_timeout_delta(ct->timeout) > (__s32)timeout)
+               ct->timeout = nfct_time_stamp + timeout;
+}
+
+static void flow_offload_fixup_ct_state(struct nf_conn *ct)
+{
+       if (nf_ct_protonum(ct) == IPPROTO_TCP)
+               flow_offload_fixup_tcp(&ct->proto.tcp);
+}
+
+static void flow_offload_fixup_ct(struct nf_conn *ct)
+{
+       flow_offload_fixup_ct_state(ct);
+       flow_offload_fixup_ct_timeout(ct);
 }
 
 void flow_offload_free(struct flow_offload *flow)
@@ -208,6 +222,11 @@ int flow_offload_add(struct nf_flowtable *flow_table, struct flow_offload *flow)
 }
 EXPORT_SYMBOL_GPL(flow_offload_add);
 
+static inline bool nf_flow_has_expired(const struct flow_offload *flow)
+{
+       return nf_flow_timeout_delta(flow->timeout) <= 0;
+}
+
 static void flow_offload_del(struct nf_flowtable *flow_table,
                             struct flow_offload *flow)
 {
@@ -223,6 +242,11 @@ static void flow_offload_del(struct nf_flowtable *flow_table,
        e = container_of(flow, struct flow_offload_entry, flow);
        clear_bit(IPS_OFFLOAD_BIT, &e->ct->status);
 
+       if (nf_flow_has_expired(flow))
+               flow_offload_fixup_ct(e->ct);
+       else if (flow->flags & FLOW_OFFLOAD_TEARDOWN)
+               flow_offload_fixup_ct_timeout(e->ct);
+
        flow_offload_free(flow);
 }
 
@@ -298,11 +322,6 @@ nf_flow_table_iterate(struct nf_flowtable *flow_table,
        return err;
 }
 
-static inline bool nf_flow_has_expired(const struct flow_offload *flow)
-{
-       return (__s32)(flow->timeout - (u32)jiffies) <= 0;
-}
-
 static void nf_flow_offload_gc_step(struct flow_offload *flow, void *data)
 {
        struct nf_flowtable *flow_table = data;
index cdfc33517e85b5e0542195b019898bbe8efbcfa8..d68c801dd614bc3e40ec8741981a4d9b6cc1b997 100644 (file)
@@ -214,6 +214,25 @@ static bool nf_flow_exceeds_mtu(const struct sk_buff *skb, unsigned int mtu)
        return true;
 }
 
+static int nf_flow_offload_dst_check(struct dst_entry *dst)
+{
+       if (unlikely(dst_xfrm(dst)))
+               return dst_check(dst, 0) ? 0 : -1;
+
+       return 0;
+}
+
+static unsigned int nf_flow_xmit_xfrm(struct sk_buff *skb,
+                                     const struct nf_hook_state *state,
+                                     struct dst_entry *dst)
+{
+       skb_orphan(skb);
+       skb_dst_set_noref(skb, dst);
+       skb->tstamp = 0;
+       dst_output(state->net, state->sk, skb);
+       return NF_STOLEN;
+}
+
 unsigned int
 nf_flow_offload_ip_hook(void *priv, struct sk_buff *skb,
                        const struct nf_hook_state *state)
@@ -254,6 +273,11 @@ nf_flow_offload_ip_hook(void *priv, struct sk_buff *skb,
        if (nf_flow_state_check(flow, ip_hdr(skb)->protocol, skb, thoff))
                return NF_ACCEPT;
 
+       if (nf_flow_offload_dst_check(&rt->dst)) {
+               flow_offload_teardown(flow);
+               return NF_ACCEPT;
+       }
+
        if (nf_flow_nat_ip(flow, skb, thoff, dir) < 0)
                return NF_DROP;
 
@@ -261,6 +285,13 @@ nf_flow_offload_ip_hook(void *priv, struct sk_buff *skb,
        iph = ip_hdr(skb);
        ip_decrease_ttl(iph);
 
+       if (unlikely(dst_xfrm(&rt->dst))) {
+               memset(skb->cb, 0, sizeof(struct inet_skb_parm));
+               IPCB(skb)->iif = skb->dev->ifindex;
+               IPCB(skb)->flags = IPSKB_FORWARDED;
+               return nf_flow_xmit_xfrm(skb, state, &rt->dst);
+       }
+
        skb->dev = outdev;
        nexthop = rt_nexthop(rt, flow->tuplehash[!dir].tuple.src_v4.s_addr);
        skb_dst_set_noref(skb, &rt->dst);
@@ -467,6 +498,11 @@ nf_flow_offload_ipv6_hook(void *priv, struct sk_buff *skb,
                                sizeof(*ip6h)))
                return NF_ACCEPT;
 
+       if (nf_flow_offload_dst_check(&rt->dst)) {
+               flow_offload_teardown(flow);
+               return NF_ACCEPT;
+       }
+
        if (skb_try_make_writable(skb, sizeof(*ip6h)))
                return NF_DROP;
 
@@ -477,6 +513,13 @@ nf_flow_offload_ipv6_hook(void *priv, struct sk_buff *skb,
        ip6h = ipv6_hdr(skb);
        ip6h->hop_limit--;
 
+       if (unlikely(dst_xfrm(&rt->dst))) {
+               memset(skb->cb, 0, sizeof(struct inet6_skb_parm));
+               IP6CB(skb)->iif = skb->dev->ifindex;
+               IP6CB(skb)->flags = IP6SKB_FORWARDED;
+               return nf_flow_xmit_xfrm(skb, state, &rt->dst);
+       }
+
        skb->dev = outdev;
        nexthop = rt6_nexthop(rt, &flow->tuplehash[!dir].tuple.src_v6);
        skb_dst_set_noref(skb, &rt->dst);
index 605a7cfe7ca79ef316fa091bd913fd3827e61deb..d47469f824a10a8628c165cedef587a49528c725 100644 (file)
@@ -138,9 +138,14 @@ static void nft_set_trans_bind(const struct nft_ctx *ctx, struct nft_set *set)
                return;
 
        list_for_each_entry_reverse(trans, &net->nft.commit_list, list) {
-               if (trans->msg_type == NFT_MSG_NEWSET &&
-                   nft_trans_set(trans) == set) {
-                       set->bound = true;
+               switch (trans->msg_type) {
+               case NFT_MSG_NEWSET:
+                       if (nft_trans_set(trans) == set)
+                               nft_trans_set_bound(trans) = true;
+                       break;
+               case NFT_MSG_NEWSETELEM:
+                       if (nft_trans_elem_set(trans) == set)
+                               nft_trans_elem_set_bound(trans) = true;
                        break;
                }
        }
@@ -1662,6 +1667,10 @@ static int nf_tables_addchain(struct nft_ctx *ctx, u8 family, u8 genmask,
 
                chain->flags |= NFT_BASE_CHAIN | flags;
                basechain->policy = NF_ACCEPT;
+               if (chain->flags & NFT_CHAIN_HW_OFFLOAD &&
+                   nft_chain_offload_priority(basechain) < 0)
+                       return -EOPNOTSUPP;
+
                flow_block_init(&basechain->flow_block);
        } else {
                chain = kzalloc(sizeof(*chain), GFP_KERNEL);
@@ -6906,7 +6915,7 @@ static int __nf_tables_abort(struct net *net)
                        break;
                case NFT_MSG_NEWSET:
                        trans->ctx.table->use--;
-                       if (nft_trans_set(trans)->bound) {
+                       if (nft_trans_set_bound(trans)) {
                                nft_trans_destroy(trans);
                                break;
                        }
@@ -6918,7 +6927,7 @@ static int __nf_tables_abort(struct net *net)
                        nft_trans_destroy(trans);
                        break;
                case NFT_MSG_NEWSETELEM:
-                       if (nft_trans_elem_set(trans)->bound) {
+                       if (nft_trans_elem_set_bound(trans)) {
                                nft_trans_destroy(trans);
                                break;
                        }
index 64f5fd5f240e262cdb3382b244018899088fc0b8..c0d18c1d77ac05e0c9b1f98a33f2e18616bc3add 100644 (file)
@@ -103,10 +103,11 @@ void nft_offload_update_dependency(struct nft_offload_ctx *ctx,
 }
 
 static void nft_flow_offload_common_init(struct flow_cls_common_offload *common,
-                                        __be16 proto,
-                                       struct netlink_ext_ack *extack)
+                                        __be16 proto, int priority,
+                                        struct netlink_ext_ack *extack)
 {
        common->protocol = proto;
+       common->prio = priority;
        common->extack = extack;
 }
 
@@ -124,6 +125,15 @@ static int nft_setup_cb_call(struct nft_base_chain *basechain,
        return 0;
 }
 
+int nft_chain_offload_priority(struct nft_base_chain *basechain)
+{
+       if (basechain->ops.priority <= 0 ||
+           basechain->ops.priority > USHRT_MAX)
+               return -1;
+
+       return 0;
+}
+
 static int nft_flow_offload_rule(struct nft_trans *trans,
                                 enum flow_cls_command command)
 {
@@ -142,7 +152,8 @@ static int nft_flow_offload_rule(struct nft_trans *trans,
        if (flow)
                proto = flow->proto;
 
-       nft_flow_offload_common_init(&cls_flow.common, proto, &extack);
+       nft_flow_offload_common_init(&cls_flow.common, proto,
+                                    basechain->ops.priority, &extack);
        cls_flow.command = command;
        cls_flow.cookie = (unsigned long) rule;
        if (flow)
index aa5f571d43619a4dc21f7036986228e78b640066..060a4ed46d5e6fca0196b3c874c9758999d84e0a 100644 (file)
@@ -72,11 +72,11 @@ static void nft_flow_offload_eval(const struct nft_expr *expr,
 {
        struct nft_flow_offload *priv = nft_expr_priv(expr);
        struct nf_flowtable *flowtable = &priv->flowtable->data;
+       struct tcphdr _tcph, *tcph = NULL;
        enum ip_conntrack_info ctinfo;
        struct nf_flow_route route;
        struct flow_offload *flow;
        enum ip_conntrack_dir dir;
-       bool is_tcp = false;
        struct nf_conn *ct;
        int ret;
 
@@ -89,7 +89,10 @@ static void nft_flow_offload_eval(const struct nft_expr *expr,
 
        switch (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum) {
        case IPPROTO_TCP:
-               is_tcp = true;
+               tcph = skb_header_pointer(pkt->skb, pkt->xt.thoff,
+                                         sizeof(_tcph), &_tcph);
+               if (unlikely(!tcph || tcph->fin || tcph->rst))
+                       goto out;
                break;
        case IPPROTO_UDP:
                break;
@@ -115,7 +118,7 @@ static void nft_flow_offload_eval(const struct nft_expr *expr,
        if (!flow)
                goto err_flow_alloc;
 
-       if (is_tcp) {
+       if (tcph) {
                ct->proto.tcp.seen[0].flags |= IP_CT_TCP_FLAG_BE_LIBERAL;
                ct->proto.tcp.seen[1].flags |= IP_CT_TCP_FLAG_BE_LIBERAL;
        }
index 8d54f3047768d2272cbd28a7bcda33df800aa589..e2742b006d255f598fc98953dbb823f615d2bf9a 100644 (file)
@@ -2618,6 +2618,13 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg)
 
        mutex_lock(&po->pg_vec_lock);
 
+       /* packet_sendmsg() check on tx_ring.pg_vec was lockless,
+        * we need to confirm it under protection of pg_vec_lock.
+        */
+       if (unlikely(!po->tx_ring.pg_vec)) {
+               err = -EBUSY;
+               goto out;
+       }
        if (likely(saddr == NULL)) {
                dev     = packet_cached_dev_get(po);
                proto   = po->num;
index d09eaf1535441fbea8f1b8b6cbba052f2a23d159..0dbbfd1b648759a7d9e729188521861d8accfe8f 100644 (file)
@@ -193,7 +193,7 @@ static int rxrpc_bind(struct socket *sock, struct sockaddr *saddr, int len)
 
 service_in_use:
        write_unlock(&local->services_lock);
-       rxrpc_put_local(local);
+       rxrpc_unuse_local(local);
        ret = -EADDRINUSE;
 error_unlock:
        release_sock(&rx->sk);
@@ -402,7 +402,7 @@ EXPORT_SYMBOL(rxrpc_kernel_check_life);
  */
 void rxrpc_kernel_probe_life(struct socket *sock, struct rxrpc_call *call)
 {
-       rxrpc_propose_ACK(call, RXRPC_ACK_PING, 0, 0, true, false,
+       rxrpc_propose_ACK(call, RXRPC_ACK_PING, 0, true, false,
                          rxrpc_propose_ack_ping_for_check_life);
        rxrpc_send_ack_packet(call, true, NULL);
 }
@@ -901,7 +901,7 @@ static int rxrpc_release_sock(struct sock *sk)
        rxrpc_queue_work(&rxnet->service_conn_reaper);
        rxrpc_queue_work(&rxnet->client_conn_reaper);
 
-       rxrpc_put_local(rx->local);
+       rxrpc_unuse_local(rx->local);
        rx->local = NULL;
        key_put(rx->key);
        rx->key = NULL;
index 822f45386e31169378157fa09530fa258ec6577d..145335611af66b1e6fcd261cc532be0a72aaa6ae 100644 (file)
@@ -254,7 +254,8 @@ struct rxrpc_security {
  */
 struct rxrpc_local {
        struct rcu_head         rcu;
-       atomic_t                usage;
+       atomic_t                active_users;   /* Number of users of the local endpoint */
+       atomic_t                usage;          /* Number of references to the structure */
        struct rxrpc_net        *rxnet;         /* The network ns in which this resides */
        struct list_head        link;
        struct socket           *socket;        /* my UDP socket */
@@ -649,7 +650,6 @@ struct rxrpc_call {
 
        /* receive-phase ACK management */
        u8                      ackr_reason;    /* reason to ACK */
-       u16                     ackr_skew;      /* skew on packet being ACK'd */
        rxrpc_serial_t          ackr_serial;    /* serial of packet being ACK'd */
        rxrpc_serial_t          ackr_first_seq; /* first sequence number received */
        rxrpc_seq_t             ackr_prev_seq;  /* previous sequence number received */
@@ -743,7 +743,7 @@ int rxrpc_reject_call(struct rxrpc_sock *);
 /*
  * call_event.c
  */
-void rxrpc_propose_ACK(struct rxrpc_call *, u8, u16, u32, bool, bool,
+void rxrpc_propose_ACK(struct rxrpc_call *, u8, u32, bool, bool,
                       enum rxrpc_propose_ack_trace);
 void rxrpc_process_call(struct work_struct *);
 
@@ -1002,6 +1002,8 @@ struct rxrpc_local *rxrpc_lookup_local(struct net *, const struct sockaddr_rxrpc
 struct rxrpc_local *rxrpc_get_local(struct rxrpc_local *);
 struct rxrpc_local *rxrpc_get_local_maybe(struct rxrpc_local *);
 void rxrpc_put_local(struct rxrpc_local *);
+struct rxrpc_local *rxrpc_use_local(struct rxrpc_local *);
+void rxrpc_unuse_local(struct rxrpc_local *);
 void rxrpc_queue_local(struct rxrpc_local *);
 void rxrpc_destroy_all_locals(struct rxrpc_net *);
 
index bc2adeb3acb9c9a54728cd9419c66186c22e4906..c767679bfa5db842c3ad94c33f011a4d5854bff2 100644 (file)
@@ -43,8 +43,7 @@ static void rxrpc_propose_ping(struct rxrpc_call *call,
  * propose an ACK be sent
  */
 static void __rxrpc_propose_ACK(struct rxrpc_call *call, u8 ack_reason,
-                               u16 skew, u32 serial, bool immediate,
-                               bool background,
+                               u32 serial, bool immediate, bool background,
                                enum rxrpc_propose_ack_trace why)
 {
        enum rxrpc_propose_ack_outcome outcome = rxrpc_propose_ack_use;
@@ -69,14 +68,12 @@ static void __rxrpc_propose_ACK(struct rxrpc_call *call, u8 ack_reason,
                if (RXRPC_ACK_UPDATEABLE & (1 << ack_reason)) {
                        outcome = rxrpc_propose_ack_update;
                        call->ackr_serial = serial;
-                       call->ackr_skew = skew;
                }
                if (!immediate)
                        goto trace;
        } else if (prior > rxrpc_ack_priority[call->ackr_reason]) {
                call->ackr_reason = ack_reason;
                call->ackr_serial = serial;
-               call->ackr_skew = skew;
        } else {
                outcome = rxrpc_propose_ack_subsume;
        }
@@ -137,11 +134,11 @@ trace:
  * propose an ACK be sent, locking the call structure
  */
 void rxrpc_propose_ACK(struct rxrpc_call *call, u8 ack_reason,
-                      u16 skew, u32 serial, bool immediate, bool background,
+                      u32 serial, bool immediate, bool background,
                       enum rxrpc_propose_ack_trace why)
 {
        spin_lock_bh(&call->lock);
-       __rxrpc_propose_ACK(call, ack_reason, skew, serial,
+       __rxrpc_propose_ACK(call, ack_reason, serial,
                            immediate, background, why);
        spin_unlock_bh(&call->lock);
 }
@@ -239,7 +236,7 @@ static void rxrpc_resend(struct rxrpc_call *call, unsigned long now_j)
                ack_ts = ktime_sub(now, call->acks_latest_ts);
                if (ktime_to_ns(ack_ts) < call->peer->rtt)
                        goto out;
-               rxrpc_propose_ACK(call, RXRPC_ACK_PING, 0, 0, true, false,
+               rxrpc_propose_ACK(call, RXRPC_ACK_PING, 0, true, false,
                                  rxrpc_propose_ack_ping_for_lost_ack);
                rxrpc_send_ack_packet(call, true, NULL);
                goto out;
@@ -372,7 +369,7 @@ recheck_state:
        if (time_after_eq(now, t)) {
                trace_rxrpc_timer(call, rxrpc_timer_exp_keepalive, now);
                cmpxchg(&call->keepalive_at, t, now + MAX_JIFFY_OFFSET);
-               rxrpc_propose_ACK(call, RXRPC_ACK_PING, 0, 0, true, true,
+               rxrpc_propose_ACK(call, RXRPC_ACK_PING, 0, true, true,
                                  rxrpc_propose_ack_ping_for_keepalive);
                set_bit(RXRPC_CALL_EV_PING, &call->events);
        }
@@ -407,7 +404,7 @@ recheck_state:
        send_ack = NULL;
        if (test_and_clear_bit(RXRPC_CALL_EV_ACK_LOST, &call->events)) {
                call->acks_lost_top = call->tx_top;
-               rxrpc_propose_ACK(call, RXRPC_ACK_PING, 0, 0, true, false,
+               rxrpc_propose_ACK(call, RXRPC_ACK_PING, 0, true, false,
                                  rxrpc_propose_ack_ping_for_lost_ack);
                send_ack = &call->acks_lost_ping;
        }
index 5bd6f1546e5c6d1cbcdb30881675ceefab01c5b3..dd47d465d1d3e7de3bcf72dc76611621bb2c0e6a 100644 (file)
@@ -196,15 +196,14 @@ send_extra_data:
  * Ping the other end to fill our RTT cache and to retrieve the rwind
  * and MTU parameters.
  */
-static void rxrpc_send_ping(struct rxrpc_call *call, struct sk_buff *skb,
-                           int skew)
+static void rxrpc_send_ping(struct rxrpc_call *call, struct sk_buff *skb)
 {
        struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
        ktime_t now = skb->tstamp;
 
        if (call->peer->rtt_usage < 3 ||
            ktime_before(ktime_add_ms(call->peer->rtt_last_req, 1000), now))
-               rxrpc_propose_ACK(call, RXRPC_ACK_PING, skew, sp->hdr.serial,
+               rxrpc_propose_ACK(call, RXRPC_ACK_PING, sp->hdr.serial,
                                  true, true,
                                  rxrpc_propose_ack_ping_for_params);
 }
@@ -419,8 +418,7 @@ static void rxrpc_input_dup_data(struct rxrpc_call *call, rxrpc_seq_t seq,
 /*
  * Process a DATA packet, adding the packet to the Rx ring.
  */
-static void rxrpc_input_data(struct rxrpc_call *call, struct sk_buff *skb,
-                            u16 skew)
+static void rxrpc_input_data(struct rxrpc_call *call, struct sk_buff *skb)
 {
        struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
        enum rxrpc_call_state state;
@@ -600,11 +598,11 @@ skip:
 
 ack:
        if (ack)
-               rxrpc_propose_ACK(call, ack, skew, ack_serial,
+               rxrpc_propose_ACK(call, ack, ack_serial,
                                  immediate_ack, true,
                                  rxrpc_propose_ack_input_data);
        else
-               rxrpc_propose_ACK(call, RXRPC_ACK_DELAY, skew, serial,
+               rxrpc_propose_ACK(call, RXRPC_ACK_DELAY, serial,
                                  false, true,
                                  rxrpc_propose_ack_input_data);
 
@@ -822,8 +820,7 @@ static void rxrpc_input_soft_acks(struct rxrpc_call *call, u8 *acks,
  * soft-ACK means that the packet may be discarded and retransmission
  * requested.  A phase is complete when all packets are hard-ACK'd.
  */
-static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb,
-                           u16 skew)
+static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb)
 {
        struct rxrpc_ack_summary summary = { 0 };
        struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
@@ -867,11 +864,11 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb,
        if (buf.ack.reason == RXRPC_ACK_PING) {
                _proto("Rx ACK %%%u PING Request", sp->hdr.serial);
                rxrpc_propose_ACK(call, RXRPC_ACK_PING_RESPONSE,
-                                 skew, sp->hdr.serial, true, true,
+                                 sp->hdr.serial, true, true,
                                  rxrpc_propose_ack_respond_to_ping);
        } else if (sp->hdr.flags & RXRPC_REQUEST_ACK) {
                rxrpc_propose_ACK(call, RXRPC_ACK_REQUESTED,
-                                 skew, sp->hdr.serial, true, true,
+                                 sp->hdr.serial, true, true,
                                  rxrpc_propose_ack_respond_to_ack);
        }
 
@@ -948,7 +945,7 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb,
            RXRPC_TX_ANNO_LAST &&
            summary.nr_acks == call->tx_top - hard_ack &&
            rxrpc_is_client_call(call))
-               rxrpc_propose_ACK(call, RXRPC_ACK_PING, skew, sp->hdr.serial,
+               rxrpc_propose_ACK(call, RXRPC_ACK_PING, sp->hdr.serial,
                                  false, true,
                                  rxrpc_propose_ack_ping_for_lost_reply);
 
@@ -1004,7 +1001,7 @@ static void rxrpc_input_abort(struct rxrpc_call *call, struct sk_buff *skb)
  * Process an incoming call packet.
  */
 static void rxrpc_input_call_packet(struct rxrpc_call *call,
-                                   struct sk_buff *skb, u16 skew)
+                                   struct sk_buff *skb)
 {
        struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
        unsigned long timo;
@@ -1023,11 +1020,11 @@ static void rxrpc_input_call_packet(struct rxrpc_call *call,
 
        switch (sp->hdr.type) {
        case RXRPC_PACKET_TYPE_DATA:
-               rxrpc_input_data(call, skb, skew);
+               rxrpc_input_data(call, skb);
                break;
 
        case RXRPC_PACKET_TYPE_ACK:
-               rxrpc_input_ack(call, skb, skew);
+               rxrpc_input_ack(call, skb);
                break;
 
        case RXRPC_PACKET_TYPE_BUSY:
@@ -1108,8 +1105,12 @@ static void rxrpc_post_packet_to_local(struct rxrpc_local *local,
 {
        _enter("%p,%p", local, skb);
 
-       skb_queue_tail(&local->event_queue, skb);
-       rxrpc_queue_local(local);
+       if (rxrpc_get_local_maybe(local)) {
+               skb_queue_tail(&local->event_queue, skb);
+               rxrpc_queue_local(local);
+       } else {
+               rxrpc_free_skb(skb, rxrpc_skb_rx_freed);
+       }
 }
 
 /*
@@ -1119,8 +1120,12 @@ static void rxrpc_reject_packet(struct rxrpc_local *local, struct sk_buff *skb)
 {
        CHECK_SLAB_OKAY(&local->usage);
 
-       skb_queue_tail(&local->reject_queue, skb);
-       rxrpc_queue_local(local);
+       if (rxrpc_get_local_maybe(local)) {
+               skb_queue_tail(&local->reject_queue, skb);
+               rxrpc_queue_local(local);
+       } else {
+               rxrpc_free_skb(skb, rxrpc_skb_rx_freed);
+       }
 }
 
 /*
@@ -1173,7 +1178,6 @@ int rxrpc_input_packet(struct sock *udp_sk, struct sk_buff *skb)
        struct rxrpc_peer *peer = NULL;
        struct rxrpc_sock *rx = NULL;
        unsigned int channel;
-       int skew = 0;
 
        _enter("%p", udp_sk);
 
@@ -1301,15 +1305,8 @@ int rxrpc_input_packet(struct sock *udp_sk, struct sk_buff *skb)
                        goto out;
                }
 
-               /* Note the serial number skew here */
-               skew = (int)sp->hdr.serial - (int)conn->hi_serial;
-               if (skew >= 0) {
-                       if (skew > 0)
-                               conn->hi_serial = sp->hdr.serial;
-               } else {
-                       skew = -skew;
-                       skew = min(skew, 65535);
-               }
+               if ((int)sp->hdr.serial - (int)conn->hi_serial > 0)
+                       conn->hi_serial = sp->hdr.serial;
 
                /* Call-bound packets are routed by connection channel. */
                channel = sp->hdr.cid & RXRPC_CHANNELMASK;
@@ -1372,11 +1369,11 @@ int rxrpc_input_packet(struct sock *udp_sk, struct sk_buff *skb)
                call = rxrpc_new_incoming_call(local, rx, skb);
                if (!call)
                        goto reject_packet;
-               rxrpc_send_ping(call, skb, skew);
+               rxrpc_send_ping(call, skb);
                mutex_unlock(&call->user_mutex);
        }
 
-       rxrpc_input_call_packet(call, skb, skew);
+       rxrpc_input_call_packet(call, skb);
        goto discard;
 
 discard:
index b1c71bad510b7c0200b2efed2a1652ecf254ca67..72a6e12a9304f8dbade52afcbca1019f5e28b1b5 100644 (file)
@@ -79,6 +79,7 @@ static struct rxrpc_local *rxrpc_alloc_local(struct rxrpc_net *rxnet,
        local = kzalloc(sizeof(struct rxrpc_local), GFP_KERNEL);
        if (local) {
                atomic_set(&local->usage, 1);
+               atomic_set(&local->active_users, 1);
                local->rxnet = rxnet;
                INIT_LIST_HEAD(&local->link);
                INIT_WORK(&local->processor, rxrpc_local_processor);
@@ -92,7 +93,7 @@ static struct rxrpc_local *rxrpc_alloc_local(struct rxrpc_net *rxnet,
                local->debug_id = atomic_inc_return(&rxrpc_debug_id);
                memcpy(&local->srx, srx, sizeof(*srx));
                local->srx.srx_service = 0;
-               trace_rxrpc_local(local, rxrpc_local_new, 1, NULL);
+               trace_rxrpc_local(local->debug_id, rxrpc_local_new, 1, NULL);
        }
 
        _leave(" = %p", local);
@@ -266,11 +267,8 @@ struct rxrpc_local *rxrpc_lookup_local(struct net *net,
                 * bind the transport socket may still fail if we're attempting
                 * to use a local address that the dying object is still using.
                 */
-               if (!rxrpc_get_local_maybe(local)) {
-                       cursor = cursor->next;
-                       list_del_init(&local->link);
+               if (!rxrpc_use_local(local))
                        break;
-               }
 
                age = "old";
                goto found;
@@ -284,7 +282,10 @@ struct rxrpc_local *rxrpc_lookup_local(struct net *net,
        if (ret < 0)
                goto sock_error;
 
-       list_add_tail(&local->link, cursor);
+       if (cursor != &rxnet->local_endpoints)
+               list_replace_init(cursor, &local->link);
+       else
+               list_add_tail(&local->link, cursor);
        age = "new";
 
 found:
@@ -320,7 +321,7 @@ struct rxrpc_local *rxrpc_get_local(struct rxrpc_local *local)
        int n;
 
        n = atomic_inc_return(&local->usage);
-       trace_rxrpc_local(local, rxrpc_local_got, n, here);
+       trace_rxrpc_local(local->debug_id, rxrpc_local_got, n, here);
        return local;
 }
 
@@ -334,7 +335,8 @@ struct rxrpc_local *rxrpc_get_local_maybe(struct rxrpc_local *local)
        if (local) {
                int n = atomic_fetch_add_unless(&local->usage, 1, 0);
                if (n > 0)
-                       trace_rxrpc_local(local, rxrpc_local_got, n + 1, here);
+                       trace_rxrpc_local(local->debug_id, rxrpc_local_got,
+                                         n + 1, here);
                else
                        local = NULL;
        }
@@ -342,24 +344,18 @@ struct rxrpc_local *rxrpc_get_local_maybe(struct rxrpc_local *local)
 }
 
 /*
- * Queue a local endpoint.
+ * Queue a local endpoint and pass the caller's reference to the work item.
  */
 void rxrpc_queue_local(struct rxrpc_local *local)
 {
        const void *here = __builtin_return_address(0);
+       unsigned int debug_id = local->debug_id;
+       int n = atomic_read(&local->usage);
 
        if (rxrpc_queue_work(&local->processor))
-               trace_rxrpc_local(local, rxrpc_local_queued,
-                                 atomic_read(&local->usage), here);
-}
-
-/*
- * A local endpoint reached its end of life.
- */
-static void __rxrpc_put_local(struct rxrpc_local *local)
-{
-       _enter("%d", local->debug_id);
-       rxrpc_queue_work(&local->processor);
+               trace_rxrpc_local(debug_id, rxrpc_local_queued, n, here);
+       else
+               rxrpc_put_local(local);
 }
 
 /*
@@ -372,10 +368,47 @@ void rxrpc_put_local(struct rxrpc_local *local)
 
        if (local) {
                n = atomic_dec_return(&local->usage);
-               trace_rxrpc_local(local, rxrpc_local_put, n, here);
+               trace_rxrpc_local(local->debug_id, rxrpc_local_put, n, here);
 
                if (n == 0)
-                       __rxrpc_put_local(local);
+                       call_rcu(&local->rcu, rxrpc_local_rcu);
+       }
+}
+
+/*
+ * Start using a local endpoint.
+ */
+struct rxrpc_local *rxrpc_use_local(struct rxrpc_local *local)
+{
+       unsigned int au;
+
+       local = rxrpc_get_local_maybe(local);
+       if (!local)
+               return NULL;
+
+       au = atomic_fetch_add_unless(&local->active_users, 1, 0);
+       if (au == 0) {
+               rxrpc_put_local(local);
+               return NULL;
+       }
+
+       return local;
+}
+
+/*
+ * Cease using a local endpoint.  Once the number of active users reaches 0, we
+ * start the closure of the transport in the work processor.
+ */
+void rxrpc_unuse_local(struct rxrpc_local *local)
+{
+       unsigned int au;
+
+       if (local) {
+               au = atomic_dec_return(&local->active_users);
+               if (au == 0)
+                       rxrpc_queue_local(local);
+               else
+                       rxrpc_put_local(local);
        }
 }
 
@@ -393,16 +426,6 @@ static void rxrpc_local_destroyer(struct rxrpc_local *local)
 
        _enter("%d", local->debug_id);
 
-       /* We can get a race between an incoming call packet queueing the
-        * processor again and the work processor starting the destruction
-        * process which will shut down the UDP socket.
-        */
-       if (local->dead) {
-               _leave(" [already dead]");
-               return;
-       }
-       local->dead = true;
-
        mutex_lock(&rxnet->local_mutex);
        list_del_init(&local->link);
        mutex_unlock(&rxnet->local_mutex);
@@ -422,13 +445,11 @@ static void rxrpc_local_destroyer(struct rxrpc_local *local)
         */
        rxrpc_purge_queue(&local->reject_queue);
        rxrpc_purge_queue(&local->event_queue);
-
-       _debug("rcu local %d", local->debug_id);
-       call_rcu(&local->rcu, rxrpc_local_rcu);
 }
 
 /*
- * Process events on an endpoint
+ * Process events on an endpoint.  The work item carries a ref which
+ * we must release.
  */
 static void rxrpc_local_processor(struct work_struct *work)
 {
@@ -436,13 +457,15 @@ static void rxrpc_local_processor(struct work_struct *work)
                container_of(work, struct rxrpc_local, processor);
        bool again;
 
-       trace_rxrpc_local(local, rxrpc_local_processing,
+       trace_rxrpc_local(local->debug_id, rxrpc_local_processing,
                          atomic_read(&local->usage), NULL);
 
        do {
                again = false;
-               if (atomic_read(&local->usage) == 0)
-                       return rxrpc_local_destroyer(local);
+               if (atomic_read(&local->active_users) == 0) {
+                       rxrpc_local_destroyer(local);
+                       break;
+               }
 
                if (!skb_queue_empty(&local->reject_queue)) {
                        rxrpc_reject_packets(local);
@@ -454,6 +477,8 @@ static void rxrpc_local_processor(struct work_struct *work)
                        again = true;
                }
        } while (again);
+
+       rxrpc_put_local(local);
 }
 
 /*
index 948e3fe249ec905208dc6966e7ff56f994ae0bac..369e516c4bdfdf3656a3f38b783ddcc70c92a5d3 100644 (file)
@@ -87,7 +87,7 @@ static size_t rxrpc_fill_out_ack(struct rxrpc_connection *conn,
        *_top = top;
 
        pkt->ack.bufferSpace    = htons(8);
-       pkt->ack.maxSkew        = htons(call->ackr_skew);
+       pkt->ack.maxSkew        = htons(0);
        pkt->ack.firstPacket    = htonl(hard_ack + 1);
        pkt->ack.previousPacket = htonl(call->ackr_prev_seq);
        pkt->ack.serial         = htonl(serial);
@@ -228,7 +228,6 @@ int rxrpc_send_ack_packet(struct rxrpc_call *call, bool ping,
                        if (ping)
                                clear_bit(RXRPC_CALL_PINGING, &call->flags);
                        rxrpc_propose_ACK(call, pkt->ack.reason,
-                                         ntohs(pkt->ack.maxSkew),
                                          ntohl(pkt->ack.serial),
                                          false, true,
                                          rxrpc_propose_ack_retry_tx);
index 5abf46cf9e6c4fa0e0271a2acdb32e24b6385870..9a7e1bc9791d7913e64e664ed08e4c17267b4331 100644 (file)
@@ -141,7 +141,7 @@ static void rxrpc_end_rx_phase(struct rxrpc_call *call, rxrpc_serial_t serial)
        ASSERTCMP(call->rx_hard_ack, ==, call->rx_top);
 
        if (call->state == RXRPC_CALL_CLIENT_RECV_REPLY) {
-               rxrpc_propose_ACK(call, RXRPC_ACK_IDLE, 0, serial, false, true,
+               rxrpc_propose_ACK(call, RXRPC_ACK_IDLE, serial, false, true,
                                  rxrpc_propose_ack_terminal_ack);
                //rxrpc_send_ack_packet(call, false, NULL);
        }
@@ -159,7 +159,7 @@ static void rxrpc_end_rx_phase(struct rxrpc_call *call, rxrpc_serial_t serial)
                call->state = RXRPC_CALL_SERVER_ACK_REQUEST;
                call->expect_req_by = jiffies + MAX_JIFFY_OFFSET;
                write_unlock_bh(&call->state_lock);
-               rxrpc_propose_ACK(call, RXRPC_ACK_DELAY, 0, serial, false, true,
+               rxrpc_propose_ACK(call, RXRPC_ACK_DELAY, serial, false, true,
                                  rxrpc_propose_ack_processing_op);
                break;
        default:
@@ -212,7 +212,7 @@ static void rxrpc_rotate_rx_window(struct rxrpc_call *call)
                if (after_eq(hard_ack, call->ackr_consumed + 2) ||
                    after_eq(top, call->ackr_seen + 2) ||
                    (hard_ack == top && after(hard_ack, call->ackr_consumed)))
-                       rxrpc_propose_ACK(call, RXRPC_ACK_DELAY, 0, serial,
+                       rxrpc_propose_ACK(call, RXRPC_ACK_DELAY, serial,
                                          true, true,
                                          rxrpc_propose_ack_rotate_rx);
                if (call->ackr_reason && call->ackr_reason != RXRPC_ACK_DELAY)
index b100870f02a6d802ef0877d5dde19380a25130d5..37dced00b63d16de7797c34ff0c10ed4812fe0b4 100644 (file)
@@ -307,6 +307,17 @@ static int tcf_skbedit_search(struct net *net, struct tc_action **a, u32 index)
        return tcf_idr_search(tn, a, index);
 }
 
+static size_t tcf_skbedit_get_fill_size(const struct tc_action *act)
+{
+       return nla_total_size(sizeof(struct tc_skbedit))
+               + nla_total_size(sizeof(u32)) /* TCA_SKBEDIT_PRIORITY */
+               + nla_total_size(sizeof(u16)) /* TCA_SKBEDIT_QUEUE_MAPPING */
+               + nla_total_size(sizeof(u32)) /* TCA_SKBEDIT_MARK */
+               + nla_total_size(sizeof(u16)) /* TCA_SKBEDIT_PTYPE */
+               + nla_total_size(sizeof(u32)) /* TCA_SKBEDIT_MASK */
+               + nla_total_size_64bit(sizeof(u64)); /* TCA_SKBEDIT_FLAGS */
+}
+
 static struct tc_action_ops act_skbedit_ops = {
        .kind           =       "skbedit",
        .id             =       TCA_ID_SKBEDIT,
@@ -316,6 +327,7 @@ static struct tc_action_ops act_skbedit_ops = {
        .init           =       tcf_skbedit_init,
        .cleanup        =       tcf_skbedit_cleanup,
        .walk           =       tcf_skbedit_walker,
+       .get_fill_size  =       tcf_skbedit_get_fill_size,
        .lookup         =       tcf_skbedit_search,
        .size           =       sizeof(struct tcf_skbedit),
 };
index c39db507ba3f42234c14e4e24184909509b9e2e7..e25d414ae12fdd9a7c4b8ea1903293e36e4ae12a 100644 (file)
@@ -1195,7 +1195,8 @@ unlock:
        spin_unlock_bh(qdisc_lock(sch));
 
 free_sched:
-       kfree(new_admin);
+       if (new_admin)
+               call_rcu(&new_admin->rcu, taprio_free_sched_cb);
 
        return err;
 }
index a554d6d15d1b6fe490ab62dd4bb1abbc96b923ab..1cf5bb5b73c412cadf1b3d7240bb8c200edb77a5 100644 (file)
@@ -546,7 +546,7 @@ static void sctp_do_8_2_transport_strike(struct sctp_cmd_seq *commands,
         */
        if (net->sctp.pf_enable &&
           (transport->state == SCTP_ACTIVE) &&
-          (asoc->pf_retrans < transport->pathmaxrxt) &&
+          (transport->error_count < transport->pathmaxrxt) &&
           (transport->error_count > asoc->pf_retrans)) {
 
                sctp_assoc_control_transport(asoc, transport,
index 25946604af85c09917e63e5c4a8d7d6fa2caebc4..e83cdaa2ab765c1ce20392b5ba2d91573f39ff14 100644 (file)
@@ -316,6 +316,7 @@ int sctp_send_reset_streams(struct sctp_association *asoc,
                nstr_list[i] = htons(str_list[i]);
 
        if (out && !sctp_stream_outq_is_empty(stream, str_nums, nstr_list)) {
+               kfree(nstr_list);
                retval = -EAGAIN;
                goto out;
        }
index b88d48d009130985db69993bc115c8cae80a71a9..0f1eaed1bd1b310833443cfb930e57d85dfa51a9 100644 (file)
@@ -75,6 +75,7 @@ void tipc_set_node_addr(struct net *net, u32 addr)
                tipc_set_node_id(net, node_id);
        }
        tn->trial_addr = addr;
+       tn->addr_trial_end = jiffies;
        pr_info("32-bit node address hash set to %x\n", addr);
 }
 
index 66d3a07bc5711ff404332e2224d139ad71daaaee..c2c5c53cad22e26e156bfe13b70fa369a32ee620 100644 (file)
@@ -106,8 +106,6 @@ struct tipc_stats {
  * @transmitq: queue for sent, non-acked messages
  * @backlogq: queue for messages waiting to be sent
  * @snt_nxt: next sequence number to use for outbound messages
- * @prev_from: sequence number of most previous retransmission request
- * @stale_limit: time when repeated identical retransmits must force link reset
  * @ackers: # of peers that needs to ack each packet before it can be released
  * @acked: # last packet acked by a certain peer. Used for broadcast.
  * @rcv_nxt: next sequence number to expect for inbound messages
@@ -164,9 +162,7 @@ struct tipc_link {
                u16 limit;
        } backlog[5];
        u16 snd_nxt;
-       u16 prev_from;
        u16 window;
-       unsigned long stale_limit;
 
        /* Reception */
        u16 rcv_nxt;
@@ -1044,47 +1040,53 @@ static void tipc_link_advance_backlog(struct tipc_link *l,
  * link_retransmit_failure() - Detect repeated retransmit failures
  * @l: tipc link sender
  * @r: tipc link receiver (= l in case of unicast)
- * @from: seqno of the 1st packet in retransmit request
  * @rc: returned code
  *
  * Return: true if the repeated retransmit failures happens, otherwise
  * false
  */
 static bool link_retransmit_failure(struct tipc_link *l, struct tipc_link *r,
-                                   u16 from, int *rc)
+                                   int *rc)
 {
        struct sk_buff *skb = skb_peek(&l->transmq);
        struct tipc_msg *hdr;
 
        if (!skb)
                return false;
-       hdr = buf_msg(skb);
 
-       /* Detect repeated retransmit failures on same packet */
-       if (r->prev_from != from) {
-               r->prev_from = from;
-               r->stale_limit = jiffies + msecs_to_jiffies(r->tolerance);
-       } else if (time_after(jiffies, r->stale_limit)) {
-               pr_warn("Retransmission failure on link <%s>\n", l->name);
-               link_print(l, "State of link ");
-               pr_info("Failed msg: usr %u, typ %u, len %u, err %u\n",
-                       msg_user(hdr), msg_type(hdr), msg_size(hdr),
-                       msg_errcode(hdr));
-               pr_info("sqno %u, prev: %x, src: %x\n",
-                       msg_seqno(hdr), msg_prevnode(hdr), msg_orignode(hdr));
-
-               trace_tipc_list_dump(&l->transmq, true, "retrans failure!");
-               trace_tipc_link_dump(l, TIPC_DUMP_NONE, "retrans failure!");
-               trace_tipc_link_dump(r, TIPC_DUMP_NONE, "retrans failure!");
+       if (!TIPC_SKB_CB(skb)->retr_cnt)
+               return false;
 
-               if (link_is_bc_sndlink(l))
-                       *rc = TIPC_LINK_DOWN_EVT;
+       if (!time_after(jiffies, TIPC_SKB_CB(skb)->retr_stamp +
+                       msecs_to_jiffies(r->tolerance)))
+               return false;
+
+       hdr = buf_msg(skb);
+       if (link_is_bc_sndlink(l) && !less(r->acked, msg_seqno(hdr)))
+               return false;
 
+       pr_warn("Retransmission failure on link <%s>\n", l->name);
+       link_print(l, "State of link ");
+       pr_info("Failed msg: usr %u, typ %u, len %u, err %u\n",
+               msg_user(hdr), msg_type(hdr), msg_size(hdr), msg_errcode(hdr));
+       pr_info("sqno %u, prev: %x, dest: %x\n",
+               msg_seqno(hdr), msg_prevnode(hdr), msg_destnode(hdr));
+       pr_info("retr_stamp %d, retr_cnt %d\n",
+               jiffies_to_msecs(TIPC_SKB_CB(skb)->retr_stamp),
+               TIPC_SKB_CB(skb)->retr_cnt);
+
+       trace_tipc_list_dump(&l->transmq, true, "retrans failure!");
+       trace_tipc_link_dump(l, TIPC_DUMP_NONE, "retrans failure!");
+       trace_tipc_link_dump(r, TIPC_DUMP_NONE, "retrans failure!");
+
+       if (link_is_bc_sndlink(l)) {
+               r->state = LINK_RESET;
+               *rc = TIPC_LINK_DOWN_EVT;
+       } else {
                *rc = tipc_link_fsm_evt(l, LINK_FAILURE_EVT);
-               return true;
        }
 
-       return false;
+       return true;
 }
 
 /* tipc_link_bc_retrans() - retransmit zero or more packets
@@ -1110,7 +1112,7 @@ static int tipc_link_bc_retrans(struct tipc_link *l, struct tipc_link *r,
 
        trace_tipc_link_retrans(r, from, to, &l->transmq);
 
-       if (link_retransmit_failure(l, r, from, &rc))
+       if (link_retransmit_failure(l, r, &rc))
                return rc;
 
        skb_queue_walk(&l->transmq, skb) {
@@ -1119,11 +1121,10 @@ static int tipc_link_bc_retrans(struct tipc_link *l, struct tipc_link *r,
                        continue;
                if (more(msg_seqno(hdr), to))
                        break;
-               if (link_is_bc_sndlink(l)) {
-                       if (time_before(jiffies, TIPC_SKB_CB(skb)->nxt_retr))
-                               continue;
-                       TIPC_SKB_CB(skb)->nxt_retr = TIPC_BC_RETR_LIM;
-               }
+
+               if (time_before(jiffies, TIPC_SKB_CB(skb)->nxt_retr))
+                       continue;
+               TIPC_SKB_CB(skb)->nxt_retr = TIPC_BC_RETR_LIM;
                _skb = __pskb_copy(skb, LL_MAX_HEADER + MIN_H_SIZE, GFP_ATOMIC);
                if (!_skb)
                        return 0;
@@ -1133,6 +1134,10 @@ static int tipc_link_bc_retrans(struct tipc_link *l, struct tipc_link *r,
                _skb->priority = TC_PRIO_CONTROL;
                __skb_queue_tail(xmitq, _skb);
                l->stats.retransmitted++;
+
+               /* Increase actual retrans counter & mark first time */
+               if (!TIPC_SKB_CB(skb)->retr_cnt++)
+                       TIPC_SKB_CB(skb)->retr_stamp = jiffies;
        }
        return 0;
 }
@@ -1357,12 +1362,10 @@ static int tipc_link_advance_transmq(struct tipc_link *l, u16 acked, u16 gap,
        struct tipc_msg *hdr;
        u16 bc_ack = l->bc_rcvlink->rcv_nxt - 1;
        u16 ack = l->rcv_nxt - 1;
+       bool passed = false;
        u16 seqno, n = 0;
        int rc = 0;
 
-       if (gap && link_retransmit_failure(l, l, acked + 1, &rc))
-               return rc;
-
        skb_queue_walk_safe(&l->transmq, skb, tmp) {
                seqno = buf_seqno(skb);
 
@@ -1372,12 +1375,17 @@ next_gap_ack:
                        __skb_unlink(skb, &l->transmq);
                        kfree_skb(skb);
                } else if (less_eq(seqno, acked + gap)) {
-                       /* retransmit skb */
+                       /* First, check if repeated retrans failures occurs? */
+                       if (!passed && link_retransmit_failure(l, l, &rc))
+                               return rc;
+                       passed = true;
+
+                       /* retransmit skb if unrestricted*/
                        if (time_before(jiffies, TIPC_SKB_CB(skb)->nxt_retr))
                                continue;
                        TIPC_SKB_CB(skb)->nxt_retr = TIPC_UC_RETR_TIME;
-
-                       _skb = __pskb_copy(skb, MIN_H_SIZE, GFP_ATOMIC);
+                       _skb = __pskb_copy(skb, LL_MAX_HEADER + MIN_H_SIZE,
+                                          GFP_ATOMIC);
                        if (!_skb)
                                continue;
                        hdr = buf_msg(_skb);
@@ -1386,6 +1394,10 @@ next_gap_ack:
                        _skb->priority = TC_PRIO_CONTROL;
                        __skb_queue_tail(xmitq, _skb);
                        l->stats.retransmitted++;
+
+                       /* Increase actual retrans counter & mark first time */
+                       if (!TIPC_SKB_CB(skb)->retr_cnt++)
+                               TIPC_SKB_CB(skb)->retr_stamp = jiffies;
                } else {
                        /* retry with Gap ACK blocks if any */
                        if (!ga || n >= ga->gack_cnt)
@@ -2577,7 +2589,7 @@ int tipc_link_dump(struct tipc_link *l, u16 dqueues, char *buf)
        i += scnprintf(buf + i, sz - i, " %x", l->peer_caps);
        i += scnprintf(buf + i, sz - i, " %u", l->silent_intv_cnt);
        i += scnprintf(buf + i, sz - i, " %u", l->rst_cnt);
-       i += scnprintf(buf + i, sz - i, " %u", l->prev_from);
+       i += scnprintf(buf + i, sz - i, " %u", 0);
        i += scnprintf(buf + i, sz - i, " %u", 0);
        i += scnprintf(buf + i, sz - i, " %u", l->acked);
 
index da509f0eb9ca48d70ef012418e2e3326d9e83563..d7ebc9e955f6a35fe6b6ac058a48c30c6218fbdc 100644 (file)
@@ -102,13 +102,15 @@ struct plist;
 #define TIPC_MEDIA_INFO_OFFSET 5
 
 struct tipc_skb_cb {
-       u32 bytes_read;
-       u32 orig_member;
        struct sk_buff *tail;
        unsigned long nxt_retr;
-       bool validated;
+       unsigned long retr_stamp;
+       u32 bytes_read;
+       u32 orig_member;
        u16 chain_imp;
        u16 ackers;
+       u16 retr_cnt;
+       bool validated;
 };
 
 #define TIPC_SKB_CB(__skb) ((struct tipc_skb_cb *)&((__skb)->cb[0]))
index 7c0b2b778703f7080c28d4919084390d4da05e7c..43922d86e5109f9b19dab68be4c950e7440ad7e8 100644 (file)
@@ -373,9 +373,9 @@ static int tls_push_data(struct sock *sk,
        struct tls_context *tls_ctx = tls_get_ctx(sk);
        struct tls_prot_info *prot = &tls_ctx->prot_info;
        struct tls_offload_context_tx *ctx = tls_offload_ctx_tx(tls_ctx);
-       int tls_push_record_flags = flags | MSG_SENDPAGE_NOTLAST;
        int more = flags & (MSG_SENDPAGE_NOTLAST | MSG_MORE);
        struct tls_record_info *record = ctx->open_record;
+       int tls_push_record_flags;
        struct page_frag *pfrag;
        size_t orig_size = size;
        u32 max_open_record_len;
@@ -390,6 +390,9 @@ static int tls_push_data(struct sock *sk,
        if (sk->sk_err)
                return -sk->sk_err;
 
+       flags |= MSG_SENDPAGE_DECRYPTED;
+       tls_push_record_flags = flags | MSG_SENDPAGE_NOTLAST;
+
        timeo = sock_sndtimeo(sk, flags & MSG_DONTWAIT);
        if (tls_is_partially_sent_record(tls_ctx)) {
                rc = tls_push_partial_record(sk, tls_ctx, flags);
@@ -576,7 +579,9 @@ void tls_device_write_space(struct sock *sk, struct tls_context *ctx)
                gfp_t sk_allocation = sk->sk_allocation;
 
                sk->sk_allocation = GFP_ATOMIC;
-               tls_push_partial_record(sk, ctx, MSG_DONTWAIT | MSG_NOSIGNAL);
+               tls_push_partial_record(sk, ctx,
+                                       MSG_DONTWAIT | MSG_NOSIGNAL |
+                                       MSG_SENDPAGE_DECRYPTED);
                sk->sk_allocation = sk_allocation;
        }
 }
index 9cbbae606ced4a12469151a523c11d3d3cfa7d7b..43252a801c3f6db298d30926aa15453b42aa1644 100644 (file)
@@ -308,6 +308,8 @@ static void tls_sk_proto_close(struct sock *sk, long timeout)
        if (free_ctx)
                icsk->icsk_ulp_data = NULL;
        sk->sk_prot = ctx->sk_proto;
+       if (sk->sk_write_space == tls_write_space)
+               sk->sk_write_space = ctx->sk_write_space;
        write_unlock_bh(&sk->sk_callback_lock);
        release_sock(sk);
        if (ctx->tx_conf == TLS_SW)
index 5215e0870bcbaf84e97db8c241260989ed74318f..6a71324be6283eccb0d816a72dd61f66b4527de6 100644 (file)
@@ -204,7 +204,11 @@ int do_pin_fd(int fd, const char *name)
        if (err)
                return err;
 
-       return bpf_obj_pin(fd, name);
+       err = bpf_obj_pin(fd, name);
+       if (err)
+               p_err("can't pin the object (%s): %s", name, strerror(errno));
+
+       return err;
 }
 
 int do_pin_any(int argc, char **argv, int (*get_fd_by_id)(__u32))
@@ -237,7 +241,7 @@ int do_pin_any(int argc, char **argv, int (*get_fd_by_id)(__u32))
 
        fd = get_fd_by_id(id);
        if (fd < 0) {
-               p_err("can't get prog by id (%u): %s", id, strerror(errno));
+               p_err("can't open object by id (%u): %s", id, strerror(errno));
                return -1;
        }
 
index f5597503c771d0790a4750f06b78c0e5edf38df8..e9ef4ca6a6557e11f809f17a93103d42af7a0e39 100644 (file)
@@ -809,7 +809,7 @@ kvp_get_ip_info(int family, char *if_name, int op,
        int sn_offset = 0;
        int error = 0;
        char *buffer;
-       struct hv_kvp_ipaddr_value *ip_buffer;
+       struct hv_kvp_ipaddr_value *ip_buffer = NULL;
        char cidr_mask[5]; /* /xyz */
        int weight;
        int i;
index 4e455018da65f76126719936d8b0672331a3b51e..a5aa7d3ac6a116a7a8d3c08d840c37a70e42e7a4 100644 (file)
@@ -1466,8 +1466,8 @@ union bpf_attr {
  *             If no cookie has been set yet, generate a new cookie. Once
  *             generated, the socket cookie remains stable for the life of the
  *             socket. This helper can be useful for monitoring per socket
- *             networking traffic statistics as it provides a unique socket
- *             identifier per namespace.
+ *             networking traffic statistics as it provides a global socket
+ *             identifier that can be assumed unique.
  *     Return
  *             A 8-byte long non-decreasing number on success, or 0 if the
  *             socket field is missing inside *skb*.
@@ -1571,8 +1571,11 @@ union bpf_attr {
  *             but this is only implemented for native XDP (with driver
  *             support) as of this writing).
  *
- *             All values for *flags* are reserved for future usage, and must
- *             be left at zero.
+ *             The lower two bits of *flags* are used as the return code if
+ *             the map lookup fails. This is so that the return value can be
+ *             one of the XDP program return codes up to XDP_TX, as chosen by
+ *             the caller. Any higher bits in the *flags* argument must be
+ *             unset.
  *
  *             When used to redirect packets to net devices, this helper
  *             provides a high performance increase over **bpf_redirect**\ ().
index 2586b6cb8f34f2ce30e382f3ddd60687f9971ecc..2b57d7ea78363a7c36da5540d67ff985a5e40963 100644 (file)
@@ -182,7 +182,6 @@ struct bpf_program {
        bpf_program_clear_priv_t clear_priv;
 
        enum bpf_attach_type expected_attach_type;
-       int btf_fd;
        void *func_info;
        __u32 func_info_rec_size;
        __u32 func_info_cnt;
@@ -313,7 +312,6 @@ void bpf_program__unload(struct bpf_program *prog)
        prog->instances.nr = -1;
        zfree(&prog->instances.fds);
 
-       zclose(prog->btf_fd);
        zfree(&prog->func_info);
        zfree(&prog->line_info);
 }
@@ -392,7 +390,6 @@ bpf_program__init(void *data, size_t size, char *section_name, int idx,
        prog->instances.fds = NULL;
        prog->instances.nr = -1;
        prog->type = BPF_PROG_TYPE_UNSPEC;
-       prog->btf_fd = -1;
 
        return 0;
 errout:
@@ -2288,9 +2285,6 @@ bpf_program_reloc_btf_ext(struct bpf_program *prog, struct bpf_object *obj,
                prog->line_info_rec_size = btf_ext__line_info_rec_size(obj->btf_ext);
        }
 
-       if (!insn_offset)
-               prog->btf_fd = btf__fd(obj->btf);
-
        return 0;
 }
 
@@ -2463,7 +2457,7 @@ load_program(struct bpf_program *prog, struct bpf_insn *insns, int insns_cnt,
        char *cp, errmsg[STRERR_BUFSIZE];
        int log_buf_size = BPF_LOG_BUF_SIZE;
        char *log_buf;
-       int ret;
+       int btf_fd, ret;
 
        if (!insns || !insns_cnt)
                return -EINVAL;
@@ -2478,7 +2472,12 @@ load_program(struct bpf_program *prog, struct bpf_insn *insns, int insns_cnt,
        load_attr.license = license;
        load_attr.kern_version = kern_version;
        load_attr.prog_ifindex = prog->prog_ifindex;
-       load_attr.prog_btf_fd = prog->btf_fd >= 0 ? prog->btf_fd : 0;
+       /* if .BTF.ext was loaded, kernel supports associated BTF for prog */
+       if (prog->obj->btf_ext)
+               btf_fd = bpf_object__btf_fd(prog->obj);
+       else
+               btf_fd = -1;
+       load_attr.prog_btf_fd = btf_fd >= 0 ? btf_fd : 0;
        load_attr.func_info = prog->func_info;
        load_attr.func_info_rec_size = prog->func_info_rec_size;
        load_attr.func_info_cnt = prog->func_info_cnt;
@@ -5000,13 +4999,15 @@ int libbpf_num_possible_cpus(void)
        static const char *fcpu = "/sys/devices/system/cpu/possible";
        int len = 0, n = 0, il = 0, ir = 0;
        unsigned int start = 0, end = 0;
+       int tmp_cpus = 0;
        static int cpus;
        char buf[128];
        int error = 0;
        int fd = -1;
 
-       if (cpus > 0)
-               return cpus;
+       tmp_cpus = READ_ONCE(cpus);
+       if (tmp_cpus > 0)
+               return tmp_cpus;
 
        fd = open(fcpu, O_RDONLY);
        if (fd < 0) {
@@ -5029,7 +5030,7 @@ int libbpf_num_possible_cpus(void)
        }
        buf[len] = '\0';
 
-       for (ir = 0, cpus = 0; ir <= len; ir++) {
+       for (ir = 0, tmp_cpus = 0; ir <= len; ir++) {
                /* Each sub string separated by ',' has format \d+-\d+ or \d+ */
                if (buf[ir] == ',' || buf[ir] == '\0') {
                        buf[ir] = '\0';
@@ -5041,13 +5042,15 @@ int libbpf_num_possible_cpus(void)
                        } else if (n == 1) {
                                end = start;
                        }
-                       cpus += end - start + 1;
+                       tmp_cpus += end - start + 1;
                        il = ir + 1;
                }
        }
-       if (cpus <= 0) {
-               pr_warning("Invalid #CPUs %d from %s\n", cpus, fcpu);
+       if (tmp_cpus <= 0) {
+               pr_warning("Invalid #CPUs %d from %s\n", tmp_cpus, fcpu);
                return -EINVAL;
        }
-       return cpus;
+
+       WRITE_ONCE(cpus, tmp_cpus);
+       return tmp_cpus;
 }
index a42cfcaa32938fb2923a84bbe59c09aac5c1526f..16d919bd133b6824f80d533a8f4c490b199023f5 100644 (file)
@@ -29,18 +29,24 @@ static int ap_is_existing_file(char *pathname)
 {
 #if !defined(_GNU_EFI) && !defined(_EDK2_EFI)
        struct stat stat_info;
+       int in_char;
 
        if (!stat(pathname, &stat_info)) {
                fprintf(stderr,
                        "Target path already exists, overwrite? [y|n] ");
 
-               if (getchar() != 'y') {
+               in_char = fgetc(stdin);
+               if (in_char == '\n') {
+                       in_char = fgetc(stdin);
+               }
+
+               if (in_char != 'y' && in_char != 'Y') {
                        return (-1);
                }
        }
 #endif
 
-       return 0;
+       return (0);
 }
 
 /******************************************************************************
index 5e980a5ab69deb857291889abb616d92507c852c..1fc4e61e9f9f0ba84b5d3329d1168446162d3cf1 100644 (file)
        .errstr = "loop detected",
        .prog_type = BPF_PROG_TYPE_TRACEPOINT,
 },
+{
+       "not-taken loop with back jump to 1st insn",
+       .insns = {
+       BPF_MOV64_IMM(BPF_REG_0, 123),
+       BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 4, -2),
+       BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+       .prog_type = BPF_PROG_TYPE_XDP,
+       .retval = 123,
+},
+{
+       "taken loop with back jump to 1st insn",
+       .insns = {
+       BPF_MOV64_IMM(BPF_REG_1, 10),
+       BPF_MOV64_IMM(BPF_REG_2, 0),
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 1),
+       BPF_EXIT_INSN(),
+       BPF_ALU64_REG(BPF_ADD, BPF_REG_2, BPF_REG_1),
+       BPF_ALU64_IMM(BPF_SUB, BPF_REG_1, 1),
+       BPF_JMP_IMM(BPF_JNE, BPF_REG_1, 0, -3),
+       BPF_MOV64_REG(BPF_REG_0, BPF_REG_2),
+       BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+       .prog_type = BPF_PROG_TYPE_XDP,
+       .retval = 55,
+},
index 4059014d93ea12ab235fa5706e36a4eb16c8c85d..4912d23844bc693d6ea97be6367d4b3022586eb3 100644 (file)
@@ -220,6 +220,8 @@ struct hv_enlightened_vmcs {
 struct hv_enlightened_vmcs *current_evmcs;
 struct hv_vp_assist_page *current_vp_assist;
 
+int vcpu_enable_evmcs(struct kvm_vm *vm, int vcpu_id);
+
 static inline int enable_vp_assist(uint64_t vp_assist_pa, void *vp_assist)
 {
        u64 val = (vp_assist_pa & HV_X64_MSR_VP_ASSIST_PAGE_ADDRESS_MASK) |
index 6cb34a0fa20053f7c37d8603f921fb86c71a6dc5..0a5e487dbc502ecf0e3ef914e9ac6061b3bdbb1b 100644 (file)
@@ -1060,9 +1060,11 @@ struct kvm_x86_state *vcpu_save_state(struct kvm_vm *vm, uint32_t vcpuid)
         TEST_ASSERT(r == 0, "Unexpected result from KVM_GET_XSAVE, r: %i",
                 r);
 
-       r = ioctl(vcpu->fd, KVM_GET_XCRS, &state->xcrs);
-        TEST_ASSERT(r == 0, "Unexpected result from KVM_GET_XCRS, r: %i",
-                r);
+       if (kvm_check_cap(KVM_CAP_XCRS)) {
+               r = ioctl(vcpu->fd, KVM_GET_XCRS, &state->xcrs);
+               TEST_ASSERT(r == 0, "Unexpected result from KVM_GET_XCRS, r: %i",
+                           r);
+       }
 
        r = ioctl(vcpu->fd, KVM_GET_SREGS, &state->sregs);
         TEST_ASSERT(r == 0, "Unexpected result from KVM_GET_SREGS, r: %i",
@@ -1103,9 +1105,11 @@ void vcpu_load_state(struct kvm_vm *vm, uint32_t vcpuid, struct kvm_x86_state *s
         TEST_ASSERT(r == 0, "Unexpected result from KVM_SET_XSAVE, r: %i",
                 r);
 
-       r = ioctl(vcpu->fd, KVM_SET_XCRS, &state->xcrs);
-        TEST_ASSERT(r == 0, "Unexpected result from KVM_SET_XCRS, r: %i",
-                r);
+       if (kvm_check_cap(KVM_CAP_XCRS)) {
+               r = ioctl(vcpu->fd, KVM_SET_XCRS, &state->xcrs);
+               TEST_ASSERT(r == 0, "Unexpected result from KVM_SET_XCRS, r: %i",
+                           r);
+       }
 
        r = ioctl(vcpu->fd, KVM_SET_SREGS, &state->sregs);
         TEST_ASSERT(r == 0, "Unexpected result from KVM_SET_SREGS, r: %i",
index 204f847bd065a66b5569c3f209c4fb3725ae5064..9cef0455b819c39688bc57551d99f8fb76abf4be 100644 (file)
 
 bool enable_evmcs;
 
+int vcpu_enable_evmcs(struct kvm_vm *vm, int vcpu_id)
+{
+       uint16_t evmcs_ver;
+
+       struct kvm_enable_cap enable_evmcs_cap = {
+               .cap = KVM_CAP_HYPERV_ENLIGHTENED_VMCS,
+                .args[0] = (unsigned long)&evmcs_ver
+       };
+
+       vcpu_ioctl(vm, vcpu_id, KVM_ENABLE_CAP, &enable_evmcs_cap);
+
+       /* KVM should return supported EVMCS version range */
+       TEST_ASSERT(((evmcs_ver >> 8) >= (evmcs_ver & 0xff)) &&
+                   (evmcs_ver & 0xff) > 0,
+                   "Incorrect EVMCS version range: %x:%x\n",
+                   evmcs_ver & 0xff, evmcs_ver >> 8);
+
+       return evmcs_ver;
+}
+
 /* Allocate memory regions for nested VMX tests.
  *
  * Input Args:
index f95c08343b487d4a4ec2698d18b08d191a612675..92915e6408e766ef8218f945545205b918286e42 100644 (file)
@@ -79,11 +79,6 @@ int main(int argc, char *argv[])
        struct kvm_x86_state *state;
        struct ucall uc;
        int stage;
-       uint16_t evmcs_ver;
-       struct kvm_enable_cap enable_evmcs_cap = {
-               .cap = KVM_CAP_HYPERV_ENLIGHTENED_VMCS,
-                .args[0] = (unsigned long)&evmcs_ver
-       };
 
        /* Create VM */
        vm = vm_create_default(VCPU_ID, 0, guest_code);
@@ -96,13 +91,7 @@ int main(int argc, char *argv[])
                exit(KSFT_SKIP);
        }
 
-       vcpu_ioctl(vm, VCPU_ID, KVM_ENABLE_CAP, &enable_evmcs_cap);
-
-       /* KVM should return supported EVMCS version range */
-       TEST_ASSERT(((evmcs_ver >> 8) >= (evmcs_ver & 0xff)) &&
-                   (evmcs_ver & 0xff) > 0,
-                   "Incorrect EVMCS version range: %x:%x\n",
-                   evmcs_ver & 0xff, evmcs_ver >> 8);
+       vcpu_enable_evmcs(vm, VCPU_ID);
 
        run = vcpu_state(vm, VCPU_ID);
 
@@ -146,7 +135,7 @@ int main(int argc, char *argv[])
                kvm_vm_restart(vm, O_RDWR);
                vm_vcpu_add(vm, VCPU_ID);
                vcpu_set_cpuid(vm, VCPU_ID, kvm_get_supported_cpuid());
-               vcpu_ioctl(vm, VCPU_ID, KVM_ENABLE_CAP, &enable_evmcs_cap);
+               vcpu_enable_evmcs(vm, VCPU_ID);
                vcpu_load_state(vm, VCPU_ID, state);
                run = vcpu_state(vm, VCPU_ID);
                free(state);
index f72b3043db0ebc99b8934fde19a61c5a60e42748..ee59831fbc98474777514a919bb9864c61f3c04a 100644 (file)
@@ -18,6 +18,7 @@
 #include "test_util.h"
 #include "kvm_util.h"
 #include "processor.h"
+#include "vmx.h"
 
 #define VCPU_ID 0
 
@@ -106,12 +107,7 @@ int main(int argc, char *argv[])
 {
        struct kvm_vm *vm;
        int rv;
-       uint16_t evmcs_ver;
        struct kvm_cpuid2 *hv_cpuid_entries;
-       struct kvm_enable_cap enable_evmcs_cap = {
-               .cap = KVM_CAP_HYPERV_ENLIGHTENED_VMCS,
-                .args[0] = (unsigned long)&evmcs_ver
-       };
 
        /* Tell stdout not to buffer its content */
        setbuf(stdout, NULL);
@@ -136,14 +132,14 @@ int main(int argc, char *argv[])
 
        free(hv_cpuid_entries);
 
-       rv = _vcpu_ioctl(vm, VCPU_ID, KVM_ENABLE_CAP, &enable_evmcs_cap);
-
-       if (rv) {
+       if (!kvm_check_cap(KVM_CAP_HYPERV_ENLIGHTENED_VMCS)) {
                fprintf(stderr,
                        "Enlightened VMCS is unsupported, skip related test\n");
                goto vm_free;
        }
 
+       vcpu_enable_evmcs(vm, VCPU_ID);
+
        hv_cpuid_entries = kvm_get_supported_hv_cpuid(vm);
        if (!hv_cpuid_entries)
                return 1;
index 40050e44ec0acd63cba5372f9a7737c2c428d62a..f9334bd3cce9f4a2fe425d8a949aa1f9e062b7ee 100644 (file)
@@ -99,8 +99,8 @@ int main(int argc, char *argv[])
        msr_platform_info = vcpu_get_msr(vm, VCPU_ID, MSR_PLATFORM_INFO);
        vcpu_set_msr(vm, VCPU_ID, MSR_PLATFORM_INFO,
                msr_platform_info | MSR_PLATFORM_INFO_MAX_TURBO_RATIO);
-       test_msr_platform_info_disabled(vm);
        test_msr_platform_info_enabled(vm);
+       test_msr_platform_info_disabled(vm);
        vcpu_set_msr(vm, VCPU_ID, MSR_PLATFORM_INFO, msr_platform_info);
 
        kvm_vm_free(vm);
index ed7218d166da6c36754b115bad4767b76378c682..853e370e8a3942c559925f37d0387e68a81aeef0 100644 (file)
 #define VMCS12_REVISION 0x11e57ed0
 #define VCPU_ID 5
 
+bool have_evmcs;
+
 void test_nested_state(struct kvm_vm *vm, struct kvm_nested_state *state)
 {
-       volatile struct kvm_run *run;
-
        vcpu_nested_state_set(vm, VCPU_ID, state, false);
-       run = vcpu_state(vm, VCPU_ID);
-       vcpu_run(vm, VCPU_ID);
-       TEST_ASSERT(run->exit_reason == KVM_EXIT_SHUTDOWN,
-               "Got exit_reason other than KVM_EXIT_SHUTDOWN: %u (%s),\n",
-               run->exit_reason,
-               exit_reason_str(run->exit_reason));
 }
 
 void test_nested_state_expect_errno(struct kvm_vm *vm,
                                    struct kvm_nested_state *state,
                                    int expected_errno)
 {
-       volatile struct kvm_run *run;
        int rv;
 
        rv = vcpu_nested_state_set(vm, VCPU_ID, state, true);
@@ -50,12 +43,6 @@ void test_nested_state_expect_errno(struct kvm_vm *vm,
                "Expected %s (%d) from vcpu_nested_state_set but got rv: %i errno: %s (%d)",
                strerror(expected_errno), expected_errno, rv, strerror(errno),
                errno);
-       run = vcpu_state(vm, VCPU_ID);
-       vcpu_run(vm, VCPU_ID);
-       TEST_ASSERT(run->exit_reason == KVM_EXIT_SHUTDOWN,
-               "Got exit_reason other than KVM_EXIT_SHUTDOWN: %u (%s),\n",
-               run->exit_reason,
-               exit_reason_str(run->exit_reason));
 }
 
 void test_nested_state_expect_einval(struct kvm_vm *vm,
@@ -90,8 +77,9 @@ void set_default_vmx_state(struct kvm_nested_state *state, int size)
 {
        memset(state, 0, size);
        state->flags = KVM_STATE_NESTED_GUEST_MODE  |
-                       KVM_STATE_NESTED_RUN_PENDING |
-                       KVM_STATE_NESTED_EVMCS;
+                       KVM_STATE_NESTED_RUN_PENDING;
+       if (have_evmcs)
+               state->flags |= KVM_STATE_NESTED_EVMCS;
        state->format = 0;
        state->size = size;
        state->hdr.vmx.vmxon_pa = 0x1000;
@@ -141,13 +129,19 @@ void test_vmx_nested_state(struct kvm_vm *vm)
        /*
         * Setting vmxon_pa == -1ull and vmcs_pa == -1ull exits early without
         * setting the nested state but flags other than eVMCS must be clear.
+        * The eVMCS flag can be set if the enlightened VMCS capability has
+        * been enabled.
         */
        set_default_vmx_state(state, state_sz);
        state->hdr.vmx.vmxon_pa = -1ull;
        state->hdr.vmx.vmcs12_pa = -1ull;
        test_nested_state_expect_einval(vm, state);
 
-       state->flags = KVM_STATE_NESTED_EVMCS;
+       state->flags &= KVM_STATE_NESTED_EVMCS;
+       if (have_evmcs) {
+               test_nested_state_expect_einval(vm, state);
+               vcpu_enable_evmcs(vm, VCPU_ID);
+       }
        test_nested_state(vm, state);
 
        /* It is invalid to have vmxon_pa == -1ull and SMM flags non-zero. */
@@ -232,6 +226,8 @@ int main(int argc, char *argv[])
        struct kvm_nested_state state;
        struct kvm_cpuid_entry2 *entry = kvm_get_supported_cpuid_entry(1);
 
+       have_evmcs = kvm_check_cap(KVM_CAP_HYPERV_ENLIGHTENED_VMCS);
+
        if (!kvm_check_cap(KVM_CAP_NESTED_STATE)) {
                printf("KVM_CAP_NESTED_STATE not available, skipping test\n");
                exit(KSFT_SKIP);
index 41476399e184f9cbb13f4541918e80fea4f18cbf..f6e65674b83cec86c215605048a81e63e0d7c20d 100755 (executable)
@@ -30,7 +30,7 @@ do_test() {
        ip netns exec "${NETNS}" ./tcp_fastopen_backup_key "$1"
        val=$(ip netns exec "${NETNS}" nstat -az | \
                grep TcpExtTCPFastOpenPassiveFail | awk '{print $2}')
-       if [ $val -ne 0 ]; then
+       if [ "$val" != 0 ]; then
                echo "FAIL: TcpExtTCPFastOpenPassiveFail non-zero"
                return 1
        fi
index fe52488a6f729b5a78eaf6dfa10230acb7abe957..16571ac1dab40267fc2141f924839aa671784d1d 100755 (executable)
@@ -321,4 +321,52 @@ else
        ip netns exec nsr1 nft list ruleset
 fi
 
+KEY_SHA="0x"$(ps -xaf | sha1sum | cut -d " " -f 1)
+KEY_AES="0x"$(ps -xaf | md5sum | cut -d " " -f 1)
+SPI1=$RANDOM
+SPI2=$RANDOM
+
+if [ $SPI1 -eq $SPI2 ]; then
+       SPI2=$((SPI2+1))
+fi
+
+do_esp() {
+    local ns=$1
+    local me=$2
+    local remote=$3
+    local lnet=$4
+    local rnet=$5
+    local spi_out=$6
+    local spi_in=$7
+
+    ip -net $ns xfrm state add src $remote dst $me proto esp spi $spi_in  enc aes $KEY_AES  auth sha1 $KEY_SHA mode tunnel sel src $rnet dst $lnet
+    ip -net $ns xfrm state add src $me  dst $remote proto esp spi $spi_out enc aes $KEY_AES auth sha1 $KEY_SHA mode tunnel sel src $lnet dst $rnet
+
+    # to encrypt packets as they go out (includes forwarded packets that need encapsulation)
+    ip -net $ns xfrm policy add src $lnet dst $rnet dir out tmpl src $me dst $remote proto esp mode tunnel priority 1 action allow
+    # to fwd decrypted packets after esp processing:
+    ip -net $ns xfrm policy add src $rnet dst $lnet dir fwd tmpl src $remote dst $me proto esp mode tunnel priority 1 action allow
+
+}
+
+do_esp nsr1 192.168.10.1 192.168.10.2 10.0.1.0/24 10.0.2.0/24 $SPI1 $SPI2
+
+do_esp nsr2 192.168.10.2 192.168.10.1 10.0.2.0/24 10.0.1.0/24 $SPI2 $SPI1
+
+ip netns exec nsr1 nft delete table ip nat
+
+# restore default routes
+ip -net ns2 route del 192.168.10.1 via 10.0.2.1
+ip -net ns2 route add default via 10.0.2.1
+ip -net ns2 route add default via dead:2::1
+
+test_tcp_forwarding ns1 ns2
+if [ $? -eq 0 ] ;then
+       echo "PASS: ipsec tunnel mode for ns1/ns2"
+else
+       echo "FAIL: ipsec tunnel mode for ns1/ns2"
+       ip netns exec nsr1 nft list ruleset 1>&2
+       ip netns exec nsr1 cat /proc/net/xfrm_stat 1>&2
+fi
+
 exit $ret
index bf5ebf59c2d4b9ce18f3f4900c42afcd0f7b7985..9cdd2e31ac2c5bff88be689b6b95ec822ef22e66 100644 (file)
         "teardown": [
             "$TC actions flush action skbedit"
         ]
+    },
+    {
+        "id": "630c",
+        "name": "Add batch of 32 skbedit actions with all parameters and cookie",
+        "category": [
+            "actions",
+            "skbedit"
+        ],
+        "setup": [
+            [
+                "$TC actions flush action skbedit",
+                0,
+                1,
+                255
+            ]
+        ],
+        "cmdUnderTest": "bash -c \"for i in \\`seq 1 32\\`; do cmd=\\\"action skbedit queue_mapping 2 priority 10 mark 7/0xaabbccdd ptype host inheritdsfield index \\$i cookie aabbccddeeff112233445566778800a1 \\\"; args=\"\\$args\\$cmd\"; done && $TC actions add \\$args\"",
+        "expExitCode": "0",
+        "verifyCmd": "$TC actions list action skbedit",
+        "matchPattern": "^[ \t]+index [0-9]+ ref",
+        "matchCount": "32",
+        "teardown": [
+            "$TC actions flush action skbedit"
+        ]
+    },
+    {
+        "id": "706d",
+        "name": "Delete batch of 32 skbedit actions with all parameters",
+        "category": [
+            "actions",
+            "skbedit"
+        ],
+        "setup": [
+            [
+                "$TC actions flush action skbedit",
+                0,
+                1,
+                255
+            ],
+            "bash -c \"for i in \\`seq 1 32\\`; do cmd=\\\"action skbedit queue_mapping 2 priority 10 mark 7/0xaabbccdd ptype host inheritdsfield index \\$i \\\"; args=\\\"\\$args\\$cmd\\\"; done && $TC actions add \\$args\""
+        ],
+        "cmdUnderTest": "bash -c \"for i in \\`seq 1 32\\`; do cmd=\\\"action skbedit index \\$i \\\"; args=\"\\$args\\$cmd\"; done && $TC actions del \\$args\"",
+        "expExitCode": "0",
+        "verifyCmd": "$TC actions list action skbedit",
+        "matchPattern": "^[ \t]+index [0-9]+ ref",
+        "matchCount": "0",
+        "teardown": []
     }
 ]
index a8a6a0c883f1ba4585610cad9d1e14bc535d4d33..6af5c91337f251fc4a722afb80f9c60d78a0f65e 100644 (file)
@@ -86,6 +86,12 @@ int kvm_handle_mmio_return(struct kvm_vcpu *vcpu, struct kvm_run *run)
        unsigned int len;
        int mask;
 
+       /* Detect an already handled MMIO return */
+       if (unlikely(!vcpu->mmio_needed))
+               return 0;
+
+       vcpu->mmio_needed = 0;
+
        if (!run->mmio.is_write) {
                len = run->mmio.len;
                if (len > sizeof(unsigned long))
@@ -188,6 +194,7 @@ int io_mem_abort(struct kvm_vcpu *vcpu, struct kvm_run *run,
        run->mmio.is_write      = is_write;
        run->mmio.phys_addr     = fault_ipa;
        run->mmio.len           = len;
+       vcpu->mmio_needed       = 1;
 
        if (!ret) {
                /* We handled the access successfully in the kernel. */
index bdbc297d06fb4676559dab05137a03d916d58273..e621b5d45b278b6e1d03f997849422ad3a94fe97 100644 (file)
@@ -8,6 +8,7 @@
 #include <linux/cpu.h>
 #include <linux/kvm_host.h>
 #include <kvm/arm_vgic.h>
+#include <asm/kvm_emulate.h>
 #include <asm/kvm_mmu.h>
 #include "vgic.h"
 
@@ -164,12 +165,18 @@ static int kvm_vgic_dist_init(struct kvm *kvm, unsigned int nr_spis)
                irq->vcpu = NULL;
                irq->target_vcpu = vcpu0;
                kref_init(&irq->refcount);
-               if (dist->vgic_model == KVM_DEV_TYPE_ARM_VGIC_V2) {
+               switch (dist->vgic_model) {
+               case KVM_DEV_TYPE_ARM_VGIC_V2:
                        irq->targets = 0;
                        irq->group = 0;
-               } else {
+                       break;
+               case KVM_DEV_TYPE_ARM_VGIC_V3:
                        irq->mpidr = 0;
                        irq->group = 1;
+                       break;
+               default:
+                       kfree(dist->spis);
+                       return -EINVAL;
                }
        }
        return 0;
@@ -209,7 +216,6 @@ int kvm_vgic_vcpu_init(struct kvm_vcpu *vcpu)
                irq->intid = i;
                irq->vcpu = NULL;
                irq->target_vcpu = vcpu;
-               irq->targets = 1U << vcpu->vcpu_id;
                kref_init(&irq->refcount);
                if (vgic_irq_is_sgi(i)) {
                        /* SGIs */
@@ -219,11 +225,6 @@ int kvm_vgic_vcpu_init(struct kvm_vcpu *vcpu)
                        /* PPIs */
                        irq->config = VGIC_CONFIG_LEVEL;
                }
-
-               if (dist->vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3)
-                       irq->group = 1;
-               else
-                       irq->group = 0;
        }
 
        if (!irqchip_in_kernel(vcpu->kvm))
@@ -286,10 +287,19 @@ int vgic_init(struct kvm *kvm)
 
                for (i = 0; i < VGIC_NR_PRIVATE_IRQS; i++) {
                        struct vgic_irq *irq = &vgic_cpu->private_irqs[i];
-                       if (dist->vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3)
+                       switch (dist->vgic_model) {
+                       case KVM_DEV_TYPE_ARM_VGIC_V3:
                                irq->group = 1;
-                       else
+                               irq->mpidr = kvm_vcpu_get_mpidr_aff(vcpu);
+                               break;
+                       case KVM_DEV_TYPE_ARM_VGIC_V2:
                                irq->group = 0;
+                               irq->targets = 1U << idx;
+                               break;
+                       default:
+                               ret = -EINVAL;
+                               goto out;
+                       }
                }
        }